Hi all,
I think there is a bug in the async reading of a pipe. Here is a example: mkfifo a2b mkfifo b2a a.st: f1 := File name: 'a2b'. f2 := File name: 'b2a'. aWriter := f1 writeStream. bReader := f2 readStream. counter := 0. [ aWriter nextPutAll: 'hello'; nl. aWriter flush. bReader nextLine. counter := counter + 1. (counter \\ 10000) = 0 ifTrue: [ Transcript nextPutAll: '%1 times' % {counter}; nl ] ] repeat. b.st: f1 := File name: 'a2b'. f2 := File name: 'b2a'. aReader := f1 readStream. bWriter := f2 writeStream. counter := 0. [ aReader nextLine. bWriter nextPutAll: 'hello'; nl. bWriter flush. counter := counter + 1. (counter \\ 10000) = 0 ifTrue: [ Transcript nextPutAll: '%1 times' % {counter}; nl ] ] repeat. If I run the 2 scripts in 2 windows they will hang after a short while. and sending them SIGIO will unblock them. The test is done in gst 3.2.4. The work around is to override isPipe in FileDescriptor so it always return false then the problem goes away. Obviously that totally disable async IO behavior so IO will block the whole gst. My theory: gst try hard not to do blocking io. so for pipe it first poll it, if there is no data it will setup sigio and suspend. However, if data come in after poll return but before the sigsuspend, it will hang. libgst/sysdep/posix/events.c: RETSIGTYPE file_polling_handler (int sig) { if (num_used_pollfds > 0) { _gst_disable_interrupts (true); _gst_async_call (async_signal_polled_files, NULL); _gst_enable_interrupts (true); } _gst_set_signal_handler (sig, file_polling_handler); _gst_wakeup (); } ... set_file_interrupt (fd, file_polling_handler); /* Now check if I/O was made possible while setting up our machinery... If so, exit; otherwise, wait on the semaphore and the SIGIO will wake us up. */ result = _gst_sync_file_polling (fd, cond); if (result == 0) { if (!head) head = new; else *p_tail_next = new; p_tail_next = &new->next; num_used_pollfds++; _gst_register_oop (semaphoreOOP); _gst_sync_wait (semaphoreOOP); } else xfree (new); ... Although it does a second poll after the sig handler setup trying to catch this possibility, the data could still come in after the second poll but before the _gst_sync_wait. The sig handler will trigger but it does not prevent the process going to sleep. From the look of it the problem is not limited to pipes, the same could happen to sockets as well. Possible fixes: * block SIGIO until the process is really asleep in an atomic operation. However I don't know how. I hate signals. Derek _______________________________________________ help-smalltalk mailing list [hidden email] https://lists.gnu.org/mailman/listinfo/help-smalltalk |
On 02/02/2012 01:02 PM, Derek Zhou wrote:
> Although it does a second poll after the sig handler setup trying to catch > this possibility, the data could still come in after the second poll but > before the _gst_sync_wait. The sig handler will trigger but it does not > prevent the process going to sleep. > > From the look of it the problem is not limited to pipes, the same could > happen to sockets as well. > > Possible fixes: > * block SIGIO until the process is really asleep in an atomic operation. > However I don't know how. It must be more subtle than that. The SIGIO will not be processed immediately; it will be processed before executing the next bytecode. This should close the race window with the update of the list. In fact, the second poll could be removed, I think. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] https://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Derek Zhou-2
On 02/02/2012 01:02 PM, Derek Zhou wrote:
> RETSIGTYPE > file_polling_handler (int sig) > { > if (num_used_pollfds> 0) > { > _gst_disable_interrupts (true); > _gst_async_call (async_signal_polled_files, NULL); > _gst_enable_interrupts (true); > } > > _gst_set_signal_handler (sig, file_polling_handler); > _gst_wakeup (); > } > > ... > set_file_interrupt (fd, file_polling_handler); > > /* Now check if I/O was made possible while setting up our machinery... > If so, exit; otherwise, wait on the semaphore and the SIGIO > will wake us up. */ > > result = _gst_sync_file_polling (fd, cond); > if (result == 0) > { > if (!head) > head = new; > else > *p_tail_next = new; > p_tail_next =&new->next; > > num_used_pollfds++; > _gst_register_oop (semaphoreOOP); > _gst_sync_wait (semaphoreOOP); > } > else > xfree (new); > ... > > Although it does a second poll after the sig handler setup trying to catch > this possibility, the data could still come in after the second poll but > before the _gst_sync_wait. The sig handler will trigger but it does not > prevent the process going to sleep. > > From the look of it the problem is not limited to pipes, the same could > happen to sockets as well. Holger, can you give the attached patch a try? Paolo _______________________________________________ help-smalltalk mailing list [hidden email] https://lists.gnu.org/mailman/listinfo/help-smalltalk fix.patch (2K) Download Attachment |
On Thu, Feb 02, 2012 at 01:39:41PM +0100, Paolo Bonzini wrote:
> On 02/02/2012 01:02 PM, Derek Zhou wrote: > >RETSIGTYPE > >file_polling_handler (int sig) > >{ > > if (num_used_pollfds> 0) > > { > > _gst_disable_interrupts (true); > > _gst_async_call (async_signal_polled_files, NULL); > > _gst_enable_interrupts (true); > > } > > > > _gst_set_signal_handler (sig, file_polling_handler); > > _gst_wakeup (); > >} > > > >... > > set_file_interrupt (fd, file_polling_handler); > > > > /* Now check if I/O was made possible while setting up our machinery... > > If so, exit; otherwise, wait on the semaphore and the SIGIO > > will wake us up. */ > > > > result = _gst_sync_file_polling (fd, cond); > > if (result == 0) > > { > > if (!head) > > head = new; > > else > > *p_tail_next = new; > > p_tail_next =&new->next; > > > > num_used_pollfds++; > > _gst_register_oop (semaphoreOOP); > > _gst_sync_wait (semaphoreOOP); > > } > > else > > xfree (new); > >... > > > >Although it does a second poll after the sig handler setup trying to catch > >this possibility, the data could still come in after the second poll but > >before the _gst_sync_wait. The sig handler will trigger but it does not > >prevent the process going to sleep. > > > > From the look of it the problem is not limited to pipes, the same could > >happen to sockets as well. > > Huh, the race is of course on setting num_used_pollfds. Stupid me. > Holger, can you give the attached patch a try? > > Paolo > Derek _______________________________________________ help-smalltalk mailing list [hidden email] https://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |