caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* more patches (for Unix signal mask)
@ 1999-05-16 21:40 Joerg Czeranski
  1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Joerg Czeranski @ 1999-05-16 21:40 UTC (permalink / raw)
  To: caml-list

Hi!

I had a look at the web interface to Caml's CVS repository
and noticed that my previous patches are already incorporated
(except for byterun/intern.c, but I'm not so sure that it makes
a difference at all). :-)

The DEC/Compaq C compiler people acknowledged that the sigsetjmp()
handling in byterun/interp.c is a bug and they promised to fix
it in a later compiler version.

Now for my new O'Caml problems:

An exception raised from C code (e.g. in the Unix module for every
system call error) resets the current signal mask -
by calling siglongjmp() in the bytecode interpreter or in
default_reset_sigmask() for native binaries.

I'm porting a small shell to O'Caml and it's mandatory that SIGCHLD
stays blocked while process group data structures are modified, because
the SIGCHLD handler has to modify them, too.

I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is
allowed to modify the signal mask, too, as per Single Unix Spec v2)
and handled jumps out of signal handlers separately.

Tracing the resulting binaries for the 2*3 cases that I know -
raise in Caml code vs. raise in C code and
raise without signal handlers vs. raise out of asynchronously
handled signal vs. raise out of synchronously handled signal -
seems to indicate that signal masks retain their proper values.

sigaction() calls with SA_NODEFER and/or non-empty sa_mask fields
are not yet handled, but they're not supported in O'Caml 2.02's
Sys module anyway.

The Single Unix Spec advises against using _setjmp() and for using
sigsetjmp(), but I don't know how that could work without mistreating
the signal mask in O'Caml.

joerch

==================== patches ====================
*** byterun/interp.c.orig	Mon Mar 15 16:07:12 1999
--- byterun/interp.c	Sun May 16 22:23:02 1999
***************
*** 201,207 ****
    initial_external_raise = external_raise;
    callback_depth++;
  
!   if (sigsetjmp(raise_buf.buf, 1)) {
      local_roots = initial_local_roots;
      accu = exn_bucket;
      goto raise_exception;
--- 201,207 ----
    initial_external_raise = external_raise;
    callback_depth++;
  
!   if (_setjmp(raise_buf.buf)) {
      local_roots = initial_local_roots;
      accu = exn_bucket;
      goto raise_exception;
*** byterun/fail.h.orig	Fri Nov 20 16:36:26 1998
--- byterun/fail.h	Sun May 16 00:31:31 1999
***************
*** 30,46 ****
  #define STACK_OVERFLOW_EXN 8    /* "Stack_overflow" */
  #define SYS_BLOCKED_IO 9        /* "Sys_blocked_io" */
  
- #ifdef POSIX_SIGNALS
  struct longjmp_buffer {
-   sigjmp_buf buf;
- };
- #else
- struct longjmp_buffer {
    jmp_buf buf;
  };
- #define sigsetjmp(buf,save) setjmp(buf)
- #define siglongjmp(buf,val) longjmp(buf,val)
- #endif
  
  extern struct longjmp_buffer * external_raise;
  extern value exn_bucket;
--- 30,38 ----
*** byterun/fail.c.orig	Sun Feb 14 17:48:22 1999
--- byterun/fail.c	Sun May 16 01:13:01 1999
***************
*** 32,38 ****
    Unlock_exn();
    exn_bucket = v;
    if (external_raise == NULL) fatal_uncaught_exception(v);
!   siglongjmp(external_raise->buf, 1);
  }
  
  void raise_constant(value tag)
--- 32,38 ----
    Unlock_exn();
    exn_bucket = v;
    if (external_raise == NULL) fatal_uncaught_exception(v);
!   _longjmp(external_raise->buf, 1);
  }
  
  void raise_constant(value tag)
*** byterun/debugger.c.orig	Tue Sep  2 14:53:57 1997
--- byterun/debugger.c	Sun May 16 01:13:37 1999
***************
*** 149,155 ****
  
    /* Catch exceptions raised by output_val */
    saved_external_raise = external_raise;
!   if (sigsetjmp(raise_buf.buf, 1) == 0) {
      external_raise = &raise_buf;
      output_val(chan, val, Val_unit);
    } else {
--- 149,155 ----
  
    /* Catch exceptions raised by output_val */
    saved_external_raise = external_raise;
!   if (_setjmp(raise_buf.buf) == 0) {
      external_raise = &raise_buf;
      output_val(chan, val, Val_unit);
    } else {
*** byterun/signals.c.orig	Mon Oct 26 20:18:04 1998
--- byterun/signals.c	Sun May 16 01:13:49 1999
***************
*** 45,53 ****
  #endif
  #endif
    if (async_signal_mode){
!     leave_blocking_section ();
!     execute_signal(signal_number);
!     enter_blocking_section ();
    }else{
      pending_signal = signal_number;
      something_to_do = 1;
--- 45,76 ----
  #endif
  #endif
    if (async_signal_mode){
!     if (external_raise == NULL) {
!       leave_blocking_section ();
!       execute_signal(signal_number);
!       enter_blocking_section ();
!     } else {
!       struct longjmp_buffer raise_buf, *saved_external_raise;
! 
!       saved_external_raise = external_raise;
!       if (_setjmp(raise_buf.buf))
!       {
! 	sigset_t s;
! 
! 	external_raise = saved_external_raise;
! 	sigemptyset(&s);
! 	sigaddset(&s, signal_number);
! 	sigprocmask(SIG_UNBLOCK, &s, NULL);
! 	_longjmp(external_raise->buf, 1);
!       }
!       else
!       {
! 	external_raise = &raise_buf;
!         leave_blocking_section ();
!         execute_signal(signal_number);
!         enter_blocking_section ();
!       }
!     }
    }else{
      pending_signal = signal_number;
      something_to_do = 1;
*** asmrun/stack.h.orig	Wed Nov 18 19:10:52 1998
--- asmrun/stack.h	Sun May 16 02:31:25 1999
***************
*** 85,89 ****
--- 85,95 ----
  extern value caml_globals[];
  extern long * caml_frametable[];
  
+ struct caml_sigblock_node {
+   struct caml_sigblock_node *next;
+   int signal_number;
+ };
+ 
+ extern struct caml_sigblock_node *caml_sigblock_stack;
  
  #endif /* _stack_ */
*** asmrun/fail.c.orig	Thu Nov 26 11:00:51 1998
--- asmrun/fail.c	Sun May 16 02:48:11 1999
***************
*** 36,41 ****
--- 36,42 ----
  
  static void default_reset_sigmask(void)
  {
+ #if 0
  #ifdef POSIX_SIGNALS
    sigset_t mask;
    sigemptyset(&mask);
***************
*** 45,50 ****
--- 46,52 ----
    sigsetmask(0);
  #endif
  #endif
+ #endif
  }
  
  void (*caml_reset_sigmask)(void) = default_reset_sigmask;
***************
*** 55,66 ****
--- 57,79 ----
  
  char * caml_exception_pointer = NULL;
  
+ struct caml_sigblock_node *caml_sigblock_stack = NULL;
+ 
+ 
  void mlraise(value v)
  {
+   sigset_t s;
+   int do_unblock;
+   struct caml_sigblock_node *stack;
+ 
    (*caml_reset_sigmask)();
    Unlock_exn();
    if (caml_exception_pointer == NULL) fatal_uncaught_exception(v);
  
+   sigemptyset(&s);
+   do_unblock = 0;
+   stack = caml_sigblock_stack;
+ 
  #ifndef Stack_grows_upwards
  #define PUSHED_AFTER <
  #else
***************
*** 70,76 ****
--- 83,102 ----
           (char *) local_roots PUSHED_AFTER caml_exception_pointer) {
      local_roots = local_roots->next;
    }
+ 
+   while (stack != NULL &&
+          (char *)stack PUSHED_AFTER caml_exception_pointer) {
+     sigaddset(&s, stack->signal_number);
+     do_unblock = 1;
+     stack = stack->next;
+   }
  #undef PUSHED_AFTER
+ 
+   if (do_unblock)
+   {
+     sigprocmask(SIG_UNBLOCK, &s, NULL);
+     caml_sigblock_stack = stack;
+   }
  
    raise_caml_exception(v);
  }
*** asmrun/signals.c.orig	Thu Nov 26 11:08:37 1998
--- asmrun/signals.c	Sun May 16 02:39:14 1999
***************
*** 115,123 ****
--- 115,131 ----
    if (async_signal_mode) {
      /* We are interrupting a C function blocked on I/O.
         Callback the Caml code immediately. */
+     struct caml_sigblock_node sigblock_node;
+ 
+     sigblock_node.next = caml_sigblock_stack;
+     sigblock_node.signal_number = sig;
+     caml_sigblock_stack = &sigblock_node;
+ 
      leave_blocking_section();
      callback(Field(signal_handlers, sig), Val_int(sig));
      enter_blocking_section();
+ 
+     caml_sigblock_stack = sigblock_node.next;
    } else {
      /* We can't execute the signal code immediately.
         Instead, we remember the signal and play with the allocation limit
==================== end of patches ====================




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Are exceptions evil? (was: more patches)
  1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski
@ 1999-05-17 11:03 ` Joerg Czeranski
  1999-05-18  1:25 ` UPDATE: more patches Joerg Czeranski
  1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy
  2 siblings, 0 replies; 7+ messages in thread
From: Joerg Czeranski @ 1999-05-17 11:03 UTC (permalink / raw)
  To: caml-list

This morning I rethought my patches under the shower and found another
bug (signals are not blocked while the handler is executed, if the
signal was caught with async_signal_mode == 0).

It's not difficult to fix, I'll do that later.  Even the signal
loss race condition can be fixed without too much thought.

But that's because signals are easy to control, they move down the
stack (for stacks growing down).  They won't bypass interrupted
functions, they only return to them after being handled.

Exceptions on the other hand go straight up the stack until they find
a handler, and then *immediately* invalidate the handler.
In a non-pure programming language like O'Caml this creates unavoidable
race conditions:

	let resource = acquire () in
	try
		use resource;
		release resource
	with e ->
		release resource;
		raise e

"release" is never called if two exceptions arrive at virtually
the same time, and neither if an exception arrives after the call
to "acquire", but before the "try".

N.b.: For me acquire is usually Unix.openfile, but it could as well
be a native O'Caml function with sideeffects (like "incr semaphore").

I think the fundamental reason for this problem is that exceptions
are thrown up the stack and not forward on the timeline of side effects.
They ought to skip new acquire calls, but never a release call for
a resource already acquired.

Is there anything that can be done about this?  Or does it require
wrapping all (relevant) side effects with monads?  Or am I missing
something?

regards,
joerch




^ permalink raw reply	[flat|nested] 7+ messages in thread

* UPDATE: more patches
  1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski
  1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski
@ 1999-05-18  1:25 ` Joerg Czeranski
  1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy
  2 siblings, 0 replies; 7+ messages in thread
From: Joerg Czeranski @ 1999-05-18  1:25 UTC (permalink / raw)
  To: caml-list

Hi,
my previous patch still left a lot of race conditions, and it didn't
do anything to avoid signal loss - O'Caml 2.02 only queues one
signal and forgets all others until a handler is called.

I think these patches (to be applied on top of the previous) should
fix both of the problems.
It can also easily be extended to handle a per-signal sa_mask (see
the sigaction man page).

It requires Unix signals though.  As I have neither NT nor a Mac, I
couldn't test it on any non-Unix system.

Testing is rather difficult anyway, as some cases only happen
when multiple signals arrive at almost the same time.  Therefor there
are probably still a few bugs lurking there.

As it's almost a complete rewrite of the signal stuff, I'll
gnuzip and uuencode the patches this time. :-)

These files are affected by the patches:
  otherlibs/unix/signals.c
  byterun/signals.h
  byterun/signals.c
  byterun/interp.c
  asmrun/fail.c
  asmrun/signals.c

joerch

begin 644 patch.03.gz
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
&HJSP2```
`
end




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: more patches (for Unix signal mask)
  1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski
  1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski
  1999-05-18  1:25 ` UPDATE: more patches Joerg Czeranski
@ 1999-05-18 16:10 ` Xavier Leroy
  1999-05-19 18:32   ` Joerg Czeranski
  2 siblings, 1 reply; 7+ messages in thread
From: Xavier Leroy @ 1999-05-18 16:10 UTC (permalink / raw)
  To: Joerg Czeranski; +Cc: caml-list

> I had a look at the web interface to Caml's CVS repository
> and noticed that my previous patches are already incorporated
> (except for byterun/intern.c, but I'm not so sure that it makes
> a difference at all). :-)

I'm still not sure whether the casts are really needed or whether the
Dec C compiler is wrong in emitting a warning.

> I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is
> allowed to modify the signal mask, too, as per Single Unix Spec v2)
> and handled jumps out of signal handlers separately.

That's an interesting idea; I'll have to think about it.  By the way,
you can just do sigsetjmp(..., 0) if you don't want the signal mask to
be saved and restored; this is more portable than _setjmp.  

> Exceptions on the other hand go straight up the stack until they find
> a handler, and then *immediately* invalidate the handler.
> In a non-pure programming language like O'Caml this creates unavoidable
> race conditions:
> 	let resource = acquire () in
> 	try
> 		use resource;
> 		release resource
> 	with e ->
> 		release resource;
> 		raise e
> "release" is never called if two exceptions arrive at virtually
> the same time, and neither if an exception arrives after the call
> to "acquire", but before the "try".

Yes, asynchronous exceptions (such as those generated from a signal
handler) are very hard to use because of this.  The programming idiom
you showed above is safe for synchronous exceptions (exceptions that
can only be raised by "use resource"), however.

My take on this is that exceptions as they are implemented now are
just fine as a non-local control structure inside a sequential
program, but that something else is needed for multithreaded and
signal-based processing.  The thread cancellation model of Posix threads
is an interesting example of how inter-thread asynchronous
notifications can be made safe.

Regards,

- Xavier Leroy




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: more patches (for Unix signal mask)
  1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy
@ 1999-05-19 18:32   ` Joerg Czeranski
  1999-05-25 15:16     ` John Skaller
  0 siblings, 1 reply; 7+ messages in thread
From: Joerg Czeranski @ 1999-05-19 18:32 UTC (permalink / raw)
  To: Xavier Leroy; +Cc: caml-list

Xavier Leroy answered to my mail:
> > I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is
> > allowed to modify the signal mask, too, as per Single Unix Spec v2)
> > and handled jumps out of signal handlers separately.
> 
> That's an interesting idea; I'll have to think about it.  By the way,
> you can just do sigsetjmp(..., 0) if you don't want the signal mask to
> be saved and restored; this is more portable than _setjmp.  

Ah, I missed that in the man page, I'll have a look if it has no
unexpected side effects ;-) to use sigsetjmp(..., 0).

> > Exceptions on the other hand go straight up the stack until they find
> > a handler, and then *immediately* invalidate the handler.
> > In a non-pure programming language like O'Caml this creates unavoidable
> > race conditions:
> > 	let resource = acquire () in
> > 	try
> > 		use resource;
> > 		release resource
> > 	with e ->
> > 		release resource;
> > 		raise e
> > "release" is never called if two exceptions arrive at virtually
> > the same time, and neither if an exception arrives after the call
> > to "acquire", but before the "try".
> 
> Yes, asynchronous exceptions (such as those generated from a signal
> handler) are very hard to use because of this.  The programming idiom
> you showed above is safe for synchronous exceptions (exceptions that
> can only be raised by "use resource"), however.

What about resource problems like stack overflows and running out
of heap memory?  I think they might happen at the call to "release".
But it probably depends on the interna of the release function.

> My take on this is that exceptions as they are implemented now are
> just fine as a non-local control structure inside a sequential
> program, but that something else is needed for multithreaded and
> signal-based processing.  The thread cancellation model of Posix threads
> is an interesting example of how inter-thread asynchronous
> notifications can be made safe.

Maybe signals should be handled in a completely different way,
not via handlers, but as a special kind of input stream.
A function similar to Unix.select (even a wrapper around it) could provide
signal notification service.  Such a model might be useful for C programs
too.
I never got around to trying this idea though.  Maybe I'll try to
write such a function for O'Caml as an alternative to the Sys.signal
facility.

joerch




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: more patches (for Unix signal mask)
  1999-05-19 18:32   ` Joerg Czeranski
@ 1999-05-25 15:16     ` John Skaller
  1999-05-27 19:10       ` Xavier Leroy
  0 siblings, 1 reply; 7+ messages in thread
From: John Skaller @ 1999-05-25 15:16 UTC (permalink / raw)
  To: caml-list

At 20:32 19/05/99 +0200, Joerg Czeranski wrote:

>Maybe signals should be handled in a completely different way,
>not via handlers, but as a special kind of input stream.

Synchronous exceptions present enough difficulties without
asychronous ones. A possible systemic difference is that
while it is common to make synchronous exceptions equivalent
to non-local gotos, that is, there's no retry, asynchronous exceptions
should probably permit continuation.

For example, after a keyboard interrupt, it often makes sense to
complete some part of the current processing before responding;
so the signal handler could set a flag which is polled at an appropriate
place.

So it is my guess that when a synchronous exception occurs, the stack
should be unwound up to the handler, but for an asynchronous
exception, the handler is invoked _without_ unwinding the stack.
The handler has the choice os unwinding the stack, and thus making
the signal act like a synchronous exception, or, continuing
with the interrupted processing after changing state local to the handler 
which will cause a defered response to the signal, again synchronising
the asynchronous event.

In other words, no program can handle asynchonous events, they have
to be synchonised with the normal control flow somehow, and the purpose
of an asynchronous signal handling mechanism is to provide
a choice of alternatives.

We probably need the reverse too: a way to 
generate asynchronous exceptions. For example, a file operation
which fails due to a hardware error which is reported
with an error code could lead to generation of an asynchronous
exception which is not normally caught an exception handler.
Local synchronous handlers can be designed to handle end-of-file
conditions, but hardware errors might require a different kind of
processing, such as 'Please put the CD-ROM back in the drive!!' :-)




-------------------------------------------------------
John Skaller    email: skaller@maxtal.com.au
		http://www.maxtal.com.au/~skaller
		phone: 61-2-96600850
		snail: 10/1 Toxteth Rd, Glebe NSW 2037, Australia





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: more patches (for Unix signal mask)
  1999-05-25 15:16     ` John Skaller
@ 1999-05-27 19:10       ` Xavier Leroy
  0 siblings, 0 replies; 7+ messages in thread
From: Xavier Leroy @ 1999-05-27 19:10 UTC (permalink / raw)
  To: John Skaller, caml-list

> Synchronous exceptions present enough difficulties without
> asychronous ones. A possible systemic difference is that
> while it is common to make synchronous exceptions equivalent
> to non-local gotos, that is, there's no retry, asynchronous exceptions
> should probably permit continuation.

Actually, that's how signal handlers work in Caml (like in C): a
user-specified function is called at the earliest possible moment.
However, that function may choose to raise an exception (that's what I
called and asynchronous exception), and that's where the problems
Joerg mentioned occur.

- Xavier Leroy




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1999-05-28 15:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski
1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski
1999-05-18  1:25 ` UPDATE: more patches Joerg Czeranski
1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy
1999-05-19 18:32   ` Joerg Czeranski
1999-05-25 15:16     ` John Skaller
1999-05-27 19:10       ` Xavier Leroy

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).