Version française
Home     About     Download     Resources     Contact us    
Browse thread
yet another signal mask patch and: what's the indended semantics?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Joerg Czeranski <jc@j...>
Subject: yet another signal mask patch and: what's the indended semantics?
Hi.

These patches are again incremental.  I think most of the signal
stuff is now working.  Stream output isn't reentrant and thus must
not be used in handlers.

Generally, what's the meaning of enter_blocking_section()/
leave_blocking_section()?  Were they intended to be only used in
reentrant C functions?

And what's the semantics of the Unix.xxx functions supposed to be?
While the Single Unix C write() function never blocks are a successful
select(), Unix.write will block until all data is written unless the
descriptor is set to non-blocking mode.

So far I assumed that the semantics should be the same for C and Caml-Unix
functions with the same name.  I didn't yet try to check which functions
are merely wrappers and which implement a higher level semantics.

These questions make me hesitate to use O'Caml "in anger" for low level
Unix programming.

BTW, there are also a few prototypes missing, e.g. the
"extern char ** cstringvect();" in
otherlibs/unix/{execv.c,execve.c,execvp.c} should be
"extern char ** cstringvect(value);" - Ansi doesn't allow mixing
of prototypes and non-prototypes for the same function.

joerch

===== begin patches =====
*** asmrun/signals.c.old	Tue May 18 23:11:51 1999
--- asmrun/signals.c	Tue May 18 23:20:18 1999
***************
*** 13,18 ****
--- 13,19 ----
  
  #include <signal.h>
  #include <stdio.h>
+ #include <string.h> /* for memcpy */
  #if defined(TARGET_power) && defined(__linux)
  #include <asm/sigcontext.h>
  #endif
***************
*** 76,81 ****
--- 77,83 ----
  static void execute_signal(int signal_number, int in_handler)
  {
    struct caml_sigblock_node sigblock_node;
+   sigset_t saved_mask;
    int i;
  
    Assert (!async_signal_mode);
***************
*** 94,105 ****
    sigblock_node.signal_number = signal_number;
    caml_sigblock_stack = &sigblock_node;
  
    sigaddset(&current_signal_mask, signal_number);
    sigprocmask(SIG_SETMASK, &current_signal_mask, NULL);
  
    callback(Field(signal_handlers, signal_number), Val_int(signal_number));
  
!   sigdelset(&current_signal_mask, signal_number);
    /* don't reset the signal mask if we're in the handler, so the handler
       doesn't nest unnecessarily */
    if (!in_handler)
--- 96,108 ----
    sigblock_node.signal_number = signal_number;
    caml_sigblock_stack = &sigblock_node;
  
+   get_current_signal_mask(&saved_mask);
    sigaddset(&current_signal_mask, signal_number);
    sigprocmask(SIG_SETMASK, &current_signal_mask, NULL);
  
    callback(Field(signal_handlers, signal_number), Val_int(signal_number));
  
!   update_signal_mask(&saved_mask);
    /* don't reset the signal mask if we're in the handler, so the handler
       doesn't nest unnecessarily */
    if (!in_handler)
***************
*** 178,194 ****
    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
--- 181,189 ----
    if (async_signal_mode) {
      /* We are interrupting a C function blocked on I/O.
         Callback the Caml code immediately. */
      leave_blocking_section();
!     execute_signal(sig, 1 /* in handler */);
      enter_blocking_section();
    } else {
      /* We can't execute the signal code immediately.
         Instead, we remember the signal and play with the allocation limit
*** byterun/signals.c.old	Tue May 18 14:32:56 1999
--- byterun/signals.c	Tue May 18 15:54:41 1999
***************
*** 76,81 ****
--- 76,82 ----
  static void execute_signal(int signal_number, int in_handler)
  {
    struct longjmp_buffer raise_buf, *saved_external_raise;
+   sigset_t saved_mask;
    int i;
  
    Assert (!async_signal_mode);
***************
*** 103,114 ****
        external_raise = &raise_buf;
    }
  
    sigaddset(&current_signal_mask, signal_number);
    sigprocmask(SIG_SETMASK, &current_signal_mask, NULL);
  
    callback(Field(signal_handlers, signal_number), Val_int(signal_number));
  
!   sigdelset(&current_signal_mask, signal_number);
    /* don't reset the signal mask if we're in the handler, so the handler
       doesn't nest unnecessarily */
    if (!in_handler)
--- 104,116 ----
        external_raise = &raise_buf;
    }
  
+   get_current_signal_mask(&saved_mask);
    sigaddset(&current_signal_mask, signal_number);
    sigprocmask(SIG_SETMASK, &current_signal_mask, NULL);
  
    callback(Field(signal_handlers, signal_number), Val_int(signal_number));
  
!   update_signal_mask(&saved_mask);
    /* don't reset the signal mask if we're in the handler, so the handler
       doesn't nest unnecessarily */
    if (!in_handler)
............

*** otherlibs/unix/execv.c.orig	Tue Sep  2 14:54:33 1997
--- otherlibs/unix/execv.c	Tue May 18 15:31:55 1999
***************
*** 15,21 ****
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect();
  
  value unix_execv(value path, value args)     /* ML */
  {
--- 15,21 ----
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect(value);
  
  value unix_execv(value path, value args)     /* ML */
  {
*** otherlibs/unix/execve.c.orig	Tue Sep  2 14:54:33 1997
--- otherlibs/unix/execve.c	Tue May 18 15:31:59 1999
***************
*** 15,21 ****
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect();
  
  value unix_execve(value path, value args, value env)     /* ML */
  {
--- 15,21 ----
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect(value);
  
  value unix_execve(value path, value args, value env)     /* ML */
  {
*** otherlibs/unix/execvp.c.orig	Tue Sep  2 14:54:34 1997
--- otherlibs/unix/execvp.c	Tue May 18 15:32:03 1999
***************
*** 15,21 ****
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect();
  extern char ** environ;
  
  value unix_execvp(value path, value args)     /* ML */
--- 15,21 ----
  #include <memory.h>
  #include "unixsupport.h"
  
! extern char ** cstringvect(value);
  extern char ** environ;
  
  value unix_execvp(value path, value args)     /* ML */
===== end patches =====