@@ -78,6 +78,8 @@ typedef struct usb_globals_s /* Global USB printer information */
7878 pthread_cond_t sidechannel_thread_cond ;
7979 int sidechannel_thread_stop ;
8080 int sidechannel_thread_done ;
81+
82+ int wakeup_pipe [2 ]; /* Pipe for waking up select() in the main thread */
8183} usb_globals_t ;
8284
8385/*
@@ -188,12 +190,14 @@ print_device(const char *uri, /* I - Device URI */
188190 * print_ptr ; /* Pointer into print data buffer */
189191 fd_set input_set ; /* Input set for select() */
190192 int nfds ; /* Number of file descriptors */
193+ int nfd_max ; /* Maximum file descriptor number for select() */
191194 struct timeval * timeout , /* Timeout pointer */
192195 tv ; /* Time value */
193196 struct timespec cond_timeout ; /* pthread condition timeout */
194197 int num_opts ; /* Number of options */
195198 cups_option_t * opts ; /* Options */
196199 const char * val ; /* Option value */
200+ char dummy ; /* select() wakeup bogus data */
197201
198202
199203 load_quirks ();
@@ -205,6 +209,17 @@ print_device(const char *uri, /* I - Device URI */
205209 have_sidechannel = !fstat (CUPS_SC_FD , & sidechannel_info ) &&
206210 S_ISSOCK (sidechannel_info .st_mode );
207211
212+ /*
213+ * Create a pipe for waking up the main thread from select()...
214+ */
215+
216+ if (pipe (g .wakeup_pipe ) < 0 )
217+ {
218+ fprintf (stderr , "DEBUG: Unable to create wakeup pipe - %s\n" ,
219+ strerror (errno ));
220+ return (CUPS_BACKEND_STOP );
221+ }
222+
208223 g .wait_eof = WAIT_EOF ;
209224
210225 /*
@@ -346,12 +361,15 @@ print_device(const char *uri, /* I - Device URI */
346361 lseek (print_fd , 0 , SEEK_SET );
347362 }
348363
364+ nfd_max = (print_fd > g .wakeup_pipe [0 ] ? print_fd : g .wakeup_pipe [0 ]) + 1 ;
365+
349366 while (status == CUPS_BACKEND_OK )
350367 {
351368 FD_ZERO (& input_set );
352369
353370 if (!g .print_bytes )
354371 FD_SET (print_fd , & input_set );
372+ FD_SET (g .wakeup_pipe [0 ], & input_set );
355373
356374 /*
357375 * Calculate select timeout...
@@ -384,7 +402,7 @@ print_device(const char *uri, /* I - Device URI */
384402 pthread_cond_signal (& g .readwrite_lock_cond );
385403 pthread_mutex_unlock (& g .readwrite_lock_mutex );
386404
387- nfds = select (print_fd + 1 , & input_set , NULL , NULL , timeout );
405+ nfds = select (nfd_max , & input_set , NULL , NULL , timeout );
388406
389407 /*
390408 * Reacquire the lock...
@@ -415,15 +433,22 @@ print_device(const char *uri, /* I - Device URI */
415433 }
416434 }
417435
436+ /*
437+ * Check if we were woken up by the sidechannel thread...
438+ */
439+
440+ if (FD_ISSET (g .wakeup_pipe [0 ], & input_set ))
441+ read (g .wakeup_pipe [0 ], & dummy , 1 );
442+
418443 /*
419444 * If drain output has finished send a response...
420445 */
421446
422447 if (g .drain_output && !nfds && !g .print_bytes )
423448 {
424449 /* Send a response... */
425- cupsSideChannelWrite (CUPS_SC_CMD_DRAIN_OUTPUT , CUPS_SC_STATUS_OK , NULL , 0 , 1.0 );
426450 g .drain_output = 0 ;
451+ cupsSideChannelWrite (CUPS_SC_CMD_DRAIN_OUTPUT , CUPS_SC_STATUS_OK , NULL , 0 , 1.0 );
427452 }
428453
429454 /*
@@ -641,6 +666,13 @@ print_device(const char *uri, /* I - Device URI */
641666
642667 close_device (g .printer );
643668
669+ /*
670+ * Close the wakeup pipe...
671+ */
672+
673+ close (g .wakeup_pipe [0 ]);
674+ close (g .wakeup_pipe [1 ]);
675+
644676 /*
645677 * Clean up ....
646678 */
@@ -1885,6 +1917,17 @@ sidechannel_thread(void *reference)
18851917 stderr );
18861918
18871919 g .drain_output = 1 ;
1920+ pthread_mutex_lock (& g .readwrite_lock_mutex );
1921+ if (!g .readwrite_lock )
1922+ {
1923+ /*
1924+ * If main thread is inside select(), assume it has infinite
1925+ * timeout and needs to be woken up.
1926+ */
1927+ if (write (g .wakeup_pipe [1 ], & data , 1 ) < 0 )
1928+ fputs ("DEBUG: Error writing to wakeup pipe\n" , stderr );
1929+ }
1930+ pthread_mutex_unlock (& g .readwrite_lock_mutex );
18881931 break ;
18891932
18901933 case CUPS_SC_CMD_GET_BIDI : /* Is the connection bidirectional? */
0 commit comments