~ chicken-core (chicken-5) 61caf8a1c8cd50f7654f614d81c3225e5f72bc0a


commit 61caf8a1c8cd50f7654f614d81c3225e5f72bc0a
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri Jul 28 13:12:31 2023 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Fri Jul 28 13:12:31 2023 +0200

    Provide new thread-safe API for POSIX signals and deprecate old one

diff --git a/DEPRECATED b/DEPRECATED
index 6c2a009e..c8d19bd1 100644
--- a/DEPRECATED
+++ b/DEPRECATED
@@ -5,6 +5,9 @@ Deprecated functions and variables
 - read/source-info from the internal, undocumented module
   (chicken compiler support) is deprecated.  Instead, use
   read-with-source-info from (chicken syntax).
+- "set-signal-handler!" and "signal-handler" have been deprecated
+  in favor of "make-signal-handler" and "ignore-signal" which are
+  better suited in a multithreaded environment.
 
 5.2.1
 - current-milliseconds and its C implementations C_milliseconds and
diff --git a/NEWS b/NEWS
index 19d2f30e..19686e11 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@
     the first non-runtime option or after "-:", whichever comes first.
 
 - Core libraries
+  - Added new thread-safe API for POSIX signals ("make-signal-handler", 
+    "signal-ignore" and "signal-default") and deprecated the existing one.
   - Added "make-finalizer" to execute finalizers in a thread-safe
     manner.
   - Added weak pairs to (chicken base), with similar behaviour to Chez Scheme.
diff --git a/manual/Module (chicken process signal) b/manual/Module (chicken process signal)
index 8e40cfdc..a640f165 100644
--- a/manual/Module (chicken process signal)	
+++ b/manual/Module (chicken process signal)	
@@ -19,34 +19,41 @@ that's the case, the description contains a note.
 
 Sets an internal timer to raise the {{signal/alrm}}
 after {{SECONDS}} are elapsed.  You can use the
-{{set-signal-handler!}} procedure to write a handler for this signal.
+{{make-signal-handler}} procedure to write a handler for this signal.
 
 '''NOTE''': On native Windows builds (all except cygwin), this
 procedure is unimplemented and will raise an error.
 
-=== signal-handler
-=== set-signal-handler!
+=== make-signal-handler
 
-<procedure>(signal-handler SIGNUM)</procedure>
+<procedure>(make-signal-handler SIGNUM ...)</procedure>
 
-Returns the signal handler for the code {{SIGNUM}} or {{#f}}.
+Establishes a handler for the POSIX signals with the numbers {{SIGNUM ...}} and returns
+a procedure of zero or one argument. Should one of the given signals be raised, then it will be stored in a
+queue. Invoking the procedure returned by {{make-signal-handler}} with zero arguments or
+with the argument {{#f}} will remove the oldest
+entry in the queue and return it to the caller. Invoking the procedure with argument {{#t}} when no signal was
+raised since the creation of the signal handler or the most recent call to the handler
+will result in suspending the execution until one of the signals given in {{SIGNUM ...}}
+occurs.
 
-<procedure>(set-signal-handler! SIGNUM PROC)</procedure>
+Notes:
 
-Establishes the procedure of one argument {{PROC}} as the handler
-for the signal with the code {{SIGNUM}}. {{PROC}} is called
-with the signal number as its sole argument. If the argument {{PROC}} is {{#f}}
-then any signal handler will be removed, and the corresponding signal set to {{SIG_IGN}}.
+* when signals arrive in quick succession (specifically, before the handler for a signal has been started), then signals will be queued (up to a certain limit); the order in which the queued signals will be handled is not specified
 
-Notes
+* Any signal handlers for the signals {{signal/segv}}, {{signal/bus}}, {{signal/fpe}} and {{signal/ill}} will be ignored and these signals will always trigger an exception, unless the executable was started with the {{-:S}} runtime option. This feature is only available on platforms that support the {{sigprocmask(3)}} POSIX API function.
 
-* it is unspecified in which thread of execution the signal handler will be invoked.
+=== signal-ignore
 
-* when signals arrive in quick succession (specifically, before the handler for a signal has been started), then signals will be queued (up to a certain limit); the order in which the queued signals will be handled is not specified
+<procedure>(signal-ignore SIGNUM)</procedure>
 
-* {{(set! (signal-handler SIG) PROC)}} can be used as an alternative to {{(set-signal-handler! SIG PROC)}}
+Ignores any future occurrences if the signal {{SIGNUM}} by setting its disposition to {{SIG_IGN}}.
 
-* Any signal handlers for the signals {{signal/segv}}, {{signal/bus}}, {{signal/fpe}} and {{signal/ill}} will be ignored and these signals will always trigger an exception, unless the executable was started with the {{-:S}} runtime option. This feature is only available on platforms that support the {{sigprocmask(3)}} POSIX API function.
+=== signal-default
+
+<procedure>(signal-default SIGNUM)</procedure>
+
+Sets the default disposition for the signal {{SIGNUM}} by setting its disposition to {{SIG_DFL}}.
 
 === set-signal-mask!
 
diff --git a/posix-common.scm b/posix-common.scm
index 8ee394c0..6f7028c3 100644
--- a/posix-common.scm
+++ b/posix-common.scm
@@ -625,19 +625,46 @@ EOF
 
 ;;; Signals
 
-(set! chicken.process.signal#set-signal-handler!
+(set! chicken.process.signal#set-signal-handler!   ; DEPRECATED
   (lambda (sig proc)
     (##sys#check-fixnum sig 'set-signal-handler!)
     (##core#inline "C_establish_signal_handler" sig (and proc sig))
     (vector-set! ##sys#signal-vector sig proc) ) )
 
-(set! chicken.process.signal#signal-handler
+(set! chicken.process.signal#signal-handler   ; DEPRECATED
   (getter-with-setter
    (lambda (sig)
      (##sys#check-fixnum sig 'signal-handler)
      (##sys#slot ##sys#signal-vector sig) )
    chicken.process.signal#set-signal-handler!
    "(chicken.process.signal#signal-handler sig)"))
+                        
+(set! chicken.process.signal#make-signal-handler
+  (lambda sigs
+    (let ((q (##sys#make-event-queue)))
+      (for-each
+        (lambda (sig)
+          (##sys#check-fixnum sig 'make-signal-handler)
+          (##core#inline "C_establish_signal_handler" sig sig)
+          (vector-set! ##sys#signal-vector sig 
+                       (lambda (sig) (##sys#add-event-to-queue! q sig))))
+        sigs)
+      (lambda (#!optional wait) 
+        (if wait
+            (##sys#wait-for-next-event q)
+            (##sys#get-next-event q))))))
+                        
+(set! chicken.process.signal#signal-ignore
+  (lambda (sig)
+    (##sys#check-fixnum sig 'signal-ignore)
+    (##core#inline "C_establish_signal_handler" sig #f)
+    (vector-set! ##sys#signal-vector sig #f)))
+
+(set! chicken.process.signal#signal-default
+  (lambda (sig)
+    (##sys#check-fixnum sig 'signal-default)
+    (##core#inline "C_establish_signal_handler" sig #t)
+    (vector-set! ##sys#signal-vector sig #f)))
 
 
 ;;; Processes
diff --git a/posix.scm b/posix.scm
index b28f21b1..a082f054 100644
--- a/posix.scm
+++ b/posix.scm
@@ -263,8 +263,10 @@
 
 
 (module chicken.process.signal
-  (set-alarm! set-signal-handler! set-signal-mask!
-   signal-handler signal-mask signal-mask! signal-masked? signal-unmask!
+  (set-alarm! set-signal-mask!
+   make-signal-handler signal-ignore signal-default
+   set-signal-handler! signal-handler ; DEPRECATED
+   signal-mask signal-mask! signal-masked? signal-unmask!
    signal/abrt signal/alrm signal/break signal/bus signal/chld
    signal/cont signal/fpe signal/hup signal/ill signal/int signal/io
    signal/kill signal/pipe signal/prof signal/quit signal/segv
@@ -276,9 +278,12 @@
 
 ;; These are all set! inside the posix module
 (define set-alarm!)
-(define set-signal-handler!)
+(define set-signal-handler!) ; DEPRECATED
 (define set-signal-mask!)
-(define signal-handler)
+(define signal-handler) ; DEPRECATED
+(define make-signal-handler)
+(define signal-ignore)
+(define signal-default)
 
 (define signal-mask)
 (define signal-mask!)
diff --git a/runtime.c b/runtime.c
index 6fdd7fca..9becd2aa 100644
--- a/runtime.c
+++ b/runtime.c
@@ -4942,6 +4942,7 @@ C_regparm C_word C_fcall C_establish_signal_handler(C_word signum, C_word reason
 #endif
 
   if(reason == C_SCHEME_FALSE) C_signal(sig, SIG_IGN);
+  else if(reason == C_SCHEME_TRUE) C_signal(sig, SIG_DFL);
   else {
     signal_mapping_table[ sig ] = C_unfix(reason);
 #if defined(HAVE_SIGACTION)
diff --git a/types.db b/types.db
index 62d98126..ad4f547f 100644
--- a/types.db
+++ b/types.db
@@ -2111,9 +2111,10 @@
 ;; process.signal
 
 (chicken.process.signal#set-alarm! (#(procedure #:clean #:enforce) chicken.process#set-alarm! (integer) integer))
-(chicken.process.signal#set-signal-handler! (#(procedure #:clean #:enforce) chicken.process.signal#set-signal-handler! (fixnum (or false (procedure (fixnum) . *))) undefined))
+(chicken.process.signal#make-signal-handler (#(procedure #:clean #:enforce) chicken.process.signal#make-signal-handler (#!rest fixnum) (procedure () fixnum)))
 (chicken.process.signal#set-signal-mask! (#(procedure #:clean #:enforce) chicken.process.signal#set-signal-mask! ((list-of fixnum)) undefined))
-(chicken.process.signal#signal-handler (#(procedure #:clean #:enforce) chicken.process.signal#signal-handler (fixnum) (or false (procedure (fixnum) . *))))
+(chicken.process.signal#signal-ignore (#(procedure #:clean #:enforce) chicken.process.signal#signal-ignore (fixnum) undefined))
+(chicken.process.signal#signal-default (#(procedure #:clean #:enforce) chicken.process.signal#signal-default (fixnum) undefined))
 (chicken.process.signal#signal-mask (#(procedure #:clean) chicken.process.signal#signal-mask () fixnum))
 (chicken.process.signal#signal-mask! (#(procedure #:clean #:enforce) chicken.process.signal#signal-mask! (fixnum) undefined))
 (chicken.process.signal#signal-masked? (#(procedure #:clean #:enforce) chicken.process.signal#signal-masked? (fixnum) boolean))
Trap