Date: Fri, 28 Jan 2005 03:07:31 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: "Christian S.J. Peron" <csjp@freebsd.org> Cc: David Xu <davidxu@freebsd.org> Subject: Re: resolver un-conditionally restarts interrupted kevent Message-ID: <20050128023756.E58087@delplex.bde.org> In-Reply-To: <20050127022459.GA63961@wnpgmb11dc1-164-159.dynamic.mts.net> References: <20050127012401.GB48521@freefall.freebsd.org> <41F84C25.60903@freebsd.org> <20050127022459.GA63961@wnpgmb11dc1-164-159.dynamic.mts.net>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 26 Jan 2005, Christian S.J. Peron wrote: > On Thu, Jan 27, 2005 at 10:04:21AM +0800, David Xu wrote: [On why the kernel changes ERESTART to EINTR for kevent() and a few other interfaces like poll()] > > Because they can not be simply restarted. those interfaces > > have in/out parameters which may already be changed by kernel > > before returning, also a timeout wait can not be restarted, you > > told kernel to sleep 10 minutes, and at minute 9, it gets a signal > > and is restarted, it will return to user code after totally 19 > > minutes. Perhaps a more fundamental reason is that not restarting is part of how these interfaces work. POSIX specifies it for poll() and select(). Changing signal handler[s] to restart automatically would be very bad even if it worked for kevent(). It would break applications that want other syscalls to not be restarted, and increase problems with applications longjmping out of signal handlers. > > > 2) why do we unconditionally restart kevent in our > > > resolver code? > > > > > I think that's right because the code checks 'n < 0' first, > > it got nothing and does timeout calculation by itself, that's OK. I think it is mostly historical -- applications or perhaps the library would not be prepared for __res_send() failing for any signal. > The problem is this breaks many programs which use loops and conditions > for program termination. Some examples are ping(8) and tcpdump(1). > > I.E. you go to ping some host or process some packets without -n and > try to ctrl+c to interrupt the process, the program will not terminate > because the resolver keeps restarting the kevent system call. This problem for ping was noticed soon after ping.c:status() was changed in rev.1.12 to just set a flag. It can't be easy to fix since it has lived for 8 years since then. Just setting flags in signal handlers is very hard to implement correctly. SA_RESTART must not be used for any signal handler, and EINTR must be handled for all syscalls and perhaps some library functions that would otherwise be restarted. ping attempts this but doesn't succeed because the resolver library doesn't cooperate. top's signal handling was broken by changing its signal handler[s] to just set a flag without even attempting this. So SIGINT doesn't kill top when top is blocked in read(). > Does anyone think it would make sense to not un-conditionally restart > the system call and have EINTR (or something to this effect) propogate > back to the process through h_errno? That is what should happen. I don't know if it is practical. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050128023756.E58087>