@@ -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/*
@@ -191,12 +193,14 @@ print_device(const char *uri, /* I - Device URI */
191193 * print_ptr ; /* Pointer into print data buffer */
192194 fd_set input_set ; /* Input set for select() */
193195 int nfds ; /* Number of file descriptors */
196+ int nfd_max ; /* Maximum file descriptor number for select() */
194197 struct timeval * timeout , /* Timeout pointer */
195198 tv ; /* Time value */
196199 struct timespec cond_timeout ; /* pthread condition timeout */
197200 int num_opts ; /* Number of options */
198201 cups_option_t * opts ; /* Options */
199202 const char * val ; /* Option value */
203+ char dummy ; /* select() wakeup bogus data */
200204
201205
202206 load_quirks ();
@@ -208,6 +212,17 @@ print_device(const char *uri, /* I - Device URI */
208212 have_sidechannel = !fstat (CUPS_SC_FD , & sidechannel_info ) &&
209213 S_ISSOCK (sidechannel_info .st_mode );
210214
215+ /*
216+ * Create a pipe for waking up the main thread from select()...
217+ */
218+
219+ if (pipe (g .wakeup_pipe ) < 0 )
220+ {
221+ fprintf (stderr , "DEBUG: Unable to create wakeup pipe - %s\n" ,
222+ strerror (errno ));
223+ return (CUPS_BACKEND_STOP );
224+ }
225+
211226 g .wait_eof = WAIT_EOF ;
212227
213228 /*
@@ -349,12 +364,15 @@ print_device(const char *uri, /* I - Device URI */
349364 lseek (print_fd , 0 , SEEK_SET );
350365 }
351366
367+ nfd_max = (print_fd > g .wakeup_pipe [0 ] ? print_fd : g .wakeup_pipe [0 ]) + 1 ;
368+
352369 while (status == CUPS_BACKEND_OK )
353370 {
354371 FD_ZERO (& input_set );
355372
356373 if (!g .print_bytes )
357374 FD_SET (print_fd , & input_set );
375+ FD_SET (g .wakeup_pipe [0 ], & input_set );
358376
359377 /*
360378 * Calculate select timeout...
@@ -387,7 +405,7 @@ print_device(const char *uri, /* I - Device URI */
387405 pthread_cond_signal (& g .readwrite_lock_cond );
388406 pthread_mutex_unlock (& g .readwrite_lock_mutex );
389407
390- nfds = select (print_fd + 1 , & input_set , NULL , NULL , timeout );
408+ nfds = select (nfd_max , & input_set , NULL , NULL , timeout );
391409
392410 /*
393411 * Reacquire the lock...
@@ -418,15 +436,22 @@ print_device(const char *uri, /* I - Device URI */
418436 }
419437 }
420438
439+ /*
440+ * Check if we were woken up by the sidechannel thread...
441+ */
442+
443+ if (FD_ISSET (g .wakeup_pipe [0 ], & input_set ))
444+ read (g .wakeup_pipe [0 ], & dummy , 1 );
445+
421446 /*
422447 * If drain output has finished send a response...
423448 */
424449
425450 if (g .drain_output && !nfds && !g .print_bytes )
426451 {
427452 /* Send a response... */
428- cupsSideChannelWrite (CUPS_SC_CMD_DRAIN_OUTPUT , CUPS_SC_STATUS_OK , NULL , 0 , 1.0 );
429453 g .drain_output = 0 ;
454+ cupsSideChannelWrite (CUPS_SC_CMD_DRAIN_OUTPUT , CUPS_SC_STATUS_OK , NULL , 0 , 1.0 );
430455 }
431456
432457 /*
@@ -644,6 +669,13 @@ print_device(const char *uri, /* I - Device URI */
644669
645670 close_device (g .printer );
646671
672+ /*
673+ * Close the wakeup pipe...
674+ */
675+
676+ close (g .wakeup_pipe [0 ]);
677+ close (g .wakeup_pipe [1 ]);
678+
647679 /*
648680 * Clean up ....
649681 */
@@ -1899,6 +1931,17 @@ sidechannel_thread(void *reference)
18991931 stderr );
19001932
19011933 g .drain_output = 1 ;
1934+ pthread_mutex_lock (& g .readwrite_lock_mutex );
1935+ if (!g .readwrite_lock )
1936+ {
1937+ /*
1938+ * If main thread is inside select(), assume it has infinite
1939+ * timeout and needs to be woken up.
1940+ */
1941+ if (write (g .wakeup_pipe [1 ], & data , 1 ) < 0 )
1942+ fputs ("DEBUG: Error writing to wakeup pipe\n" , stderr );
1943+ }
1944+ pthread_mutex_unlock (& g .readwrite_lock_mutex );
19021945 break ;
19031946
19041947 case CUPS_SC_CMD_GET_BIDI : /* Is the connection bidirectional? */
0 commit comments