caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Gerd Stolpmann <info@gerd-stolpmann.de>
To: ygrek <ygrek@autistici.org>
Cc: caml-list <caml-list@inria.fr>
Subject: Re: [Caml-list] Bug when printing from signal handlers?
Date: Thu, 20 Mar 2014 21:07:22 +0100	[thread overview]
Message-ID: <1395346042.27397.33.camel@zotac> (raw)
In-Reply-To: <20140320132941.09aa04f4@kiwi.local.tld>

[-- 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 --]

  parent reply	other threads:[~2014-03-20 20:07 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-19 21:21 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 [this message]
2014-03-23 10:01         ` ygrek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1395346042.27397.33.camel@zotac \
    --to=info@gerd-stolpmann.de \
    --cc=caml-list@inria.fr \
    --cc=ygrek@autistici.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).