* [Caml-list] Bug when printing from signal handlers? @ 2014-03-19 21:21 Anders Peter Fugmann 2014-03-19 22:19 ` Jesper Louis Andersen 0 siblings, 1 reply; 7+ messages in thread From: Anders Peter Fugmann @ 2014-03-19 21:21 UTC (permalink / raw) To: caml-list Hi, I'm experiencing a live lock while printing from a signal handler. It seems to be triggered when the main is interrupted while printing. The following program exposes the problem: (tested on 4.00.1 and 4.01.0) let rec loop () = print_endline "In main thread"; loop () let _ = Sys.(set_signal sigalrm (Signal_handle (fun _ -> print_endline "In signal handler"))); let _ = Unix.(setitimer ITIMER_REAL { it_interval = 0.1; it_value = 0.1 }) in loop () For some reason, in caml_flush_parial channel->buff becomes greater than channel->curr which means caml_flush never completes, as caml_flush_partial never returns true. Is printing from a signal handler illegal? I tries searching for bug on this matter but only found examples that printed from signal handlers. Regards Anders ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-19 21:21 [Caml-list] Bug when printing from signal handlers? Anders Peter Fugmann @ 2014-03-19 22:19 ` Jesper Louis Andersen 2014-03-19 23:21 ` Gerd Stolpmann 0 siblings, 1 reply; 7+ messages in thread From: Jesper Louis Andersen @ 2014-03-19 22:19 UTC (permalink / raw) To: Anders Peter Fugmann; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 898 bytes --] On Wed, Mar 19, 2014 at 10:21 PM, Anders Peter Fugmann <anders@fugmann.net>wrote: > Is printing from a signal handler illegal? FWIW, that is illegal in some operating systems. I have seen it in one case at least: * Linux with threads. printf in C is protected by a mutex. Suppose we are inside the printf, with the mutex locked and then we get a signal. We run the handler, and it wants to print out debug information. Welcome deadlock! * Many system calls are not safe in the signal handler. FreeBSD has a list in sigaction(2) for instance. See http://www.freebsd.org/cgi/man.cgi?query=sigaction&apropos=0&sektion=0&manpath=FreeBSD+10.0-RELEASE&arch=default&format=html In practice, you should probably just set a flag in the signal handler and then handle that in a main loop of the program. Doing advanced stuff in a signal handler is usually dangerous non-compatible territory. -- J. [-- Attachment #2: Type: text/html, Size: 1711 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-19 22:19 ` Jesper Louis Andersen @ 2014-03-19 23:21 ` Gerd Stolpmann 2014-03-20 5:29 ` ygrek 0 siblings, 1 reply; 7+ messages in thread From: Gerd Stolpmann @ 2014-03-19 23:21 UTC (permalink / raw) To: Jesper Louis Andersen; +Cc: Anders Peter Fugmann, caml-list [-- Attachment #1: Type: text/plain, Size: 1994 bytes --] OCaml printing isn't printf in C - it calls directly write() and is always possible. OCaml signal handlers aren't signal handlers from the C viewpoint: When the signal is caught, a flag in the OCaml runtime is set, and this flag is regularly checked by the running code. (I.e. what you suggest is already done in the runtime.) So, I'd say this is a bug in the OCaml runtime. The bug goes away when you print to a different channel from the signal handler, so it looks like channels and signal handlers have some unwanted effect on each other. Gerd Am Mittwoch, den 19.03.2014, 23:19 +0100 schrieb Jesper Louis Andersen: > > On Wed, Mar 19, 2014 at 10:21 PM, Anders Peter Fugmann > <anders@fugmann.net> wrote: > Is printing from a signal handler illegal? > > FWIW, that is illegal in some operating systems. I have seen it in one > case at least: > > > * Linux with threads. printf in C is protected by a mutex. Suppose we > are inside the printf, with the mutex locked and then we get a signal. > We run the handler, and it wants to print out debug information. > Welcome deadlock! > * Many system calls are not safe in the signal handler. FreeBSD has a > list in sigaction(2) for instance. See > > > > http://www.freebsd.org/cgi/man.cgi?query=sigaction&apropos=0&sektion=0&manpath=FreeBSD+10.0-RELEASE&arch=default&format=html > > > In practice, you should probably just set a flag in the signal handler > and then handle that in a main loop of the program. Doing advanced > stuff in a signal handler is usually dangerous non-compatible > territory. > > > > -- > J. -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany gerd@gerd-stolpmann.de My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------ [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-19 23:21 ` Gerd Stolpmann @ 2014-03-20 5:29 ` ygrek 2014-03-20 7:42 ` Anders Fugmann 2014-03-20 20:07 ` Gerd Stolpmann 0 siblings, 2 replies; 7+ messages in thread From: ygrek @ 2014-03-20 5:29 UTC (permalink / raw) Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 1294 bytes --] On Thu, 20 Mar 2014 00:21:36 +0100 Gerd Stolpmann <info@gerd-stolpmann.de> wrote: > OCaml printing isn't printf in C - it calls directly write() and is > always possible. OCaml signal handlers aren't signal handlers from the C > viewpoint: When the signal is caught, a flag in the OCaml runtime is > set, and this flag is regularly checked by the running code. (I.e. what > you suggest is already done in the runtime.) > > So, I'd say this is a bug in the OCaml runtime. The bug goes away when > you print to a different channel from the signal handler, so it looks > like channels and signal handlers have some unwanted effect on each > other. stdlib channels are protected with non-recursive mutex, so the deadlock on re-entrant invocation is guaranteed. AFAICS runtime system tries to execute signal immediately (see signal_handle in asmrun/signals_asm.c) and if that is not possible - records signal for later execution. Anyway doing complex stuff in signal handler is a bad idea, because even with delayed processing (when things are safe from the libc point of view) the points of invocation of OCaml signal handler are scattered all around the program (allocation sites) and any OCaml resource that doesn't support reentrant usage will break the program. -- [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-20 5:29 ` ygrek @ 2014-03-20 7:42 ` Anders Fugmann 2014-03-20 20:07 ` Gerd Stolpmann 1 sibling, 0 replies; 7+ messages in thread From: Anders Fugmann @ 2014-03-20 7:42 UTC (permalink / raw) To: ygrek; +Cc: caml-list On 03/20/2014 06:29 AM, ygrek wrote: > > stdlib channels are protected with non-recursive mutex, so the deadlock on re-entrant invocation is guaranteed. I also assumed when I first saw the behavior that it was some deadlock. But it seems that that is not the case as the system enters a live lock and just sits there burning off cpu time. > AFAICS runtime system tries to execute signal immediately (see signal_handle in asmrun/signals_asm.c) > and if that is not possible - records signal for later execution. > Anyway doing complex stuff in signal handler is a bad idea, because even with delayed processing (when > things are safe from the libc point of view) the points of invocation of OCaml signal handler are scattered > all around the program (allocation sites) and any OCaml resource that doesn't support reentrant usage will break > the program. Maybe the documentation should be updated to explain how signal handling works and what is allowed in signal handers. Possibly also ideas on how to cope with these limitations. I circumvented the problem by using unbuffered writes (Unix.write), but it makes me wonder if I have code erroneous code lying around. /Anders ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-20 5:29 ` ygrek 2014-03-20 7:42 ` Anders Fugmann @ 2014-03-20 20:07 ` Gerd Stolpmann 2014-03-23 10:01 ` ygrek 1 sibling, 1 reply; 7+ messages in thread From: Gerd Stolpmann @ 2014-03-20 20:07 UTC (permalink / raw) To: ygrek; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 3028 bytes --] Am Donnerstag, den 20.03.2014, 13:29 +0800 schrieb ygrek: > On Thu, 20 Mar 2014 00:21:36 +0100 > Gerd Stolpmann <info@gerd-stolpmann.de> wrote: > > > OCaml printing isn't printf in C - it calls directly write() and is > > always possible. OCaml signal handlers aren't signal handlers from the C > > viewpoint: When the signal is caught, a flag in the OCaml runtime is > > set, and this flag is regularly checked by the running code. (I.e. what > > you suggest is already done in the runtime.) > > > > So, I'd say this is a bug in the OCaml runtime. The bug goes away when > > you print to a different channel from the signal handler, so it looks > > like channels and signal handlers have some unwanted effect on each > > other. > > stdlib channels are protected with non-recursive mutex, so the deadlock on re-entrant invocation is guaranteed. No, there aren't any mutexes here involved - the failing program is single-threaded. > AFAICS runtime system tries to execute signal immediately (see signal_handle in asmrun/signals_asm.c) > and if that is not possible - records signal for later execution. Right, this handles the case that the current thread is doing a blocking system call (sorry, forgot this case). Apparently, the OCaml code is then run directly from the signal handler. > Anyway doing complex stuff in signal handler is a bad idea, because even with delayed processing (when > things are safe from the libc point of view) the points of invocation of OCaml signal handler are scattered > all around the program (allocation sites) and any OCaml resource that doesn't support reentrant usage will break > the program. Anyway, I don't think this has anything to do with calling non-signal-safe libc functions (so far I can see the only called function is write()). It is most likely because flush isn't reentrant: caml_flush() calls caml_flush_partial() which in turn calls do_write(). The signal arrives during the write() syscall, and in the signal handler another flush is invoked, for the same channel. The effect is that (so far I see it) channel->offset and channel->curr are set to illegal values. I don't see how this can be fixed properly. You probably can avoid the livelock by doing nothing when flush is invoked for the second time, but (a) this changes the semantics of flushing, and (b) doesn't fix the other potential problems (when a flush is interrupted and one of the other channel functions is called from the signal handler). Nevertheless it's a bit surprising that innocent-looking OCaml code turns out as unsafe. The current state is a bit unsatisfactory, at least. Gerd -- ------------------------------------------------------------ Gerd Stolpmann, Darmstadt, Germany gerd@gerd-stolpmann.de My OCaml site: http://www.camlcity.org Contact details: http://www.camlcity.org/contact.html Company homepage: http://www.gerd-stolpmann.de ------------------------------------------------------------ [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] Bug when printing from signal handlers? 2014-03-20 20:07 ` Gerd Stolpmann @ 2014-03-23 10:01 ` ygrek 0 siblings, 0 replies; 7+ messages in thread From: ygrek @ 2014-03-23 10:01 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 1101 bytes --] On Thu, 20 Mar 2014 08:42:47 +0100 Anders Fugmann <anders@fugmann.net> wrote: > I circumvented the problem by using unbuffered writes (Unix.write), but > it makes me wonder if I have code erroneous code lying around. I personally prefer to use signalfd for non-trivial signal handling, which means that handler is invoked with specific and controlled program state. On Thu, 20 Mar 2014 21:07:22 +0100 Gerd Stolpmann <info@gerd-stolpmann.de> wrote: > No, there aren't any mutexes here involved - the failing program is > single-threaded. Indeed, the program is compiled with single-threaded runtime, so that's an additional failure scenario. > Nevertheless it's a bit surprising that innocent-looking OCaml code > turns out as unsafe. The current state is a bit unsatisfactory, at > least. Agreed, that's the point - OCaml signal handler though safe on the libc side, is nevertheless subject to asynchronous execution at arbitrary program spots and, unless the user code and runtime are fully reentrant, various unexpected program failures are inevitable.. -- [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-03-23 10:01 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-03-19 21:21 [Caml-list] Bug when printing from signal handlers? Anders Peter Fugmann 2014-03-19 22:19 ` Jesper Louis Andersen 2014-03-19 23:21 ` Gerd Stolpmann 2014-03-20 5:29 ` ygrek 2014-03-20 7:42 ` Anders Fugmann 2014-03-20 20:07 ` Gerd Stolpmann 2014-03-23 10:01 ` ygrek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox