Re: [Chicken-users] replace signal with sigaction

2011-10-02 Thread Jörg F . Wittenberger

Hi,

in this message
http://lists.nongnu.org/archive/html/chicken-users/2011-09/msg00292.html
I sent out a strange bug.  Sorry for that.

The child-registering fork() should be:

(define (save-fork)
(let* ((ie (##sys#fudge 14))
   (pid (begin (chicken-disable-interrupts!)
   ((foreign-lambda int fork)
  (case pid
((0) (set! processes-running (make-hash-table fx= number-hash)))
((-1) (if ie (chicken-simple-enable-interrupts!)))
(else (hash-table-set! processes-running pid (list pid))
   (if ie (chicken-simple-enable-interrupts!
  pid))

The way I miss-cutpasted it together would switch off interrupt
handling completely.  (Which I did not notice, since those changes
in signal handling would work even with interrupt disabled.

Actually this make me wonder if it would be possible to actually
remove it from the source.  Wait - I'm not proposing that hereby.

/Jörg




___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

Now let's see how we can use those modifications.

This code is far from what I'd like it to be.

It starts out with the idea, that it tries to resemble the
process-wait API as it stands.

However in the presence of green threads I feel that the API
is not the best we could have.  This translates into the weird
code to be presented.

Note that this code must be compiled with (disable-interrupts).

;; To take the load off the OS, we keep our internal table
;; of child processes.  This simplifies the waitpit call too.

(define processes-running (make-hash-table fx= number-hash))

;; Only for introspection: to cons up all the children's state:
;; (running-processes-fold cons '())
;; List entries:
;;  (pid)   = running
;;  (pid thread ...)  = those thread waiting
;;  (pid bool int)  = terminated, but no thread so far did waitforit
;;
;; Also handy for debugging.

(define (running-processes-fold f i)
 (hash-table-fold processes-running (lambda (k v i) (f v i)) i))

(define-foreign-variable C_interrupts_enabled bool C_interrupts_enabled)
(define (chicken-simple-enable-interrupts!) (set! C_interrupts_enabled #t))

;; fork the child and register it
;; Aside: You don't want to just fork if you have threads.  And you
;; don't want the install an exception handler just for the fork.

(define (save-fork)
 (chicken-disable-interrupts!)
 (let ((ie (##sys#fudge 14))
(pid ((foreign-lambda int fork
   (case pid
 ((0) (set! processes-running (make-hash-table fx= number-hash)))
 ((-1) (if ie (chicken-simple-enable-interrupts!)))
 (else (hash-table-set! processes-running pid (list pid))
(if ie (chicken-simple-enable-interrupts!
   pid))


;; Now a tentatively replacement for process-wait.  I'm not using
;; That anywhere.   Falls back to the state of affairs in pid=0

(define (alt-process-wait pid nohang)
 (if (= pid 0)
 (process-wait pid nohang
 (if nohang
 (process-test-pid pid)
 (process-wait-for-pid pid

#|

 NB:  Even though the above mimics the API it is different.

 What would have to fix the remaining race conditions wrt.
 multiple green thread waiting for the same process:
 Change the API: Refer to the process by means of a process
 structure.  That one would hold the entry we keep in the 
 processes-running table.  Threads would wait on that struct

 and we could happily remove it from the table
 right in process-waitpid-signal-pending! before we enable
 the waiting threads.

 Sadly that's not practical because of the weird API.

 Therefore we really mimic what an OS would do.

|#


(define (process-waitpid-signal-pending! e f s)
 (let ((t (cdr e)))
   (set-cdr! e (list f s))
   (for-each
(lambda (t)
  (if (and (thread? t) (eq? (##sys#slot t 3) 'blocked))
   (##sys#thread-unblock! t)
   ))
t)))

(define (process-waitpid nohang)
 (let loop ()
   (receive
(p f s) (##sys#process-wait -1 nohang) ; wait for any child process
(if (fx p 0)
 (let ((e (hash-table-ref/default processes-running p #f)))
   (if e
   (process-waitpid-signal-pending! e f s)
   (hash-table-set! processes-running p (list p f s)))
   (loop))


(define (process-signal/chld signum) (process-waitpid #t))

(set-signal-handler! signal/chld process-signal/chld)

(define (process-wait-for-pid pid)
 (##sys#check-exact pid 'process-wait-for-pid)
 (let ((e (hash-table-ref/default processes-running pid #f)))
   (if (and e (pair? (cdr e)) (not (thread? (cadr e
(begin
  (hash-table-delete! processes-running pid)
  (apply values e))
(receive
 (p f s) (##sys#process-wait pid #t)
 (if (fx= p 0)
 (let ((ct (current-thread)))
   (set-cdr! e (cons ct (cdr e)))
   (##sys#call-with-current-continuation
(lambda (return)
  (##sys#setslot ct 3 'blocked)
  (##sys#setslot ct 1 (lambda () (return #t)))
  (##sys#schedule)))
   (hash-table-delete! processes-running pid)
   (apply values e))
 (begin
   (if e (process-waitpid-signal-pending! e f s))
   (if (fx= p -1)
   (values -1 #f s)
   (values p f s

(define (process-test-pid pid)
 (##sys#check-exact pid 'process-test-pid)
 (let ((gone (hash-table-ref/default processes-running pid #f)))
   (if (and gone (pair? (cdr gone)) (not (thread? (cadr gone
(begin
  (hash-table-delete! processes-running pid)
  (apply values gone))
(receive
 (p f s) (##sys#process-wait pid #t)
 (if (and gone (fx= p pid))
 (process-waitpid-signal-pending! gone f s))
 (if (fx= p -1)
 (values pid #f s)
 (values p f s))













___
Chicken-users mailing list
Chicken-users@nongnu.org

Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

On Sep 30 2011, Jörg F. Wittenberger wrote:



;; Now a tentatively replacement for process-wait.  I'm not using
;; That anywhere.   Falls back to the state of affairs in pid=0

(define (alt-process-wait pid nohang)
 (if (= pid 0)
 (process-wait pid nohang
 (if nohang
 (process-test-pid pid)
 (process-wait-for-pid pid


That one is definitely wrong if ever use together with save-fork:

The pid = 0 case would have to signal possible waiting threads.

Forget it.  We need a better API anyway.





___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

Alan,

I figured that you did almost have you for the process-io-ports code
I cited the other day.

It might make your live easier, if I just post the code as I'm using
it right now.

Be warned: it does one thing NOT.  When there is a bad fd encountered
while reading/writing to a fd, the read/write will be aborted by
exception.  But the port will *not* be closed.



(declare
(foreign-declare #EOF

#include errno.h
#include sys/wait.h
static int io_needs_restart()
{
 switch(errno) {
  case EAGAIN:
  case EINTR:
   return 1;
  default: return 0;
}
}

EOF
))

(define process-io-ports
 (let ([make-input-port make-input-port]
	[make-output-port make-output-port] 
	[make-string make-string] 
	[substring substring]

[file-close-fd! (foreign-lambda* int ((int fd)) return(close(fd));)]
)
   (lambda (pid fdr fdw)
 (##sys#file-nonblocking! fdw)
 (##sys#file-nonblocking! fdr)  ; should not be required
 (let* ([buf (make-string buffer-size)]
 [buflen 0]
 [bufindex 0]
 [iclosed #f]
 [oclosed #f]
 [in
  (make-input-port
   (let-location
((again bool #f))
(lambda ()
  (when (fx= bufindex buflen)
(let loop ()
  (and (not iclosed)
   (let ([n ((foreign-lambda*
  int
  ((int fd) (scheme-pointer buf) (int 
s) ((c-pointer bool) again))
  int r = read(fd, buf, s); 
*again=(r==-1)io_needs_restart(); return(r);)

 fdr buf buffer-size (location again))])
 (cond
  (again
   (guard
(ex (else (format (current-error-port) read 
error ~a\n ex)
  (raise ex)))
(thread-wait-for-i/o! fdr #:input))
   (loop))
  ((eq? -1 n)
   ;; (##sys#update-errno)
   ;; (##sys#signal-hook #:process-error 
'process-io-read can not read from fd fdr strerror)

   (set! iclosed #t)
   #;(when (eq? -1 (file-close-fd! fdr))
   (##sys#update-errno)
   (##sys#signal-hook #:process-error 
'process-io-read
   can not close fd input port fdr) )
   (file-close-fd! fdr))
  (else
   ;; (print [rd:  n ])
   (set! buflen n)
   (set! bufindex 0))) ))) )
  (if (or iclosed (fx= bufindex buflen))
  (end-of-file)
  (let ([c (##core#inline C_subchar buf bufindex)])
(set! bufindex (fx+ bufindex 1))
c) ) ))
   (lambda ()
(when iclosed
  (##sys#signal-hook #:process-error input port is 
closed fdr))

 #t )
   (lambda ()
 (unless iclosed
   (set! iclosed #t)
   (when (eq? -1 (file-close-fd! fdr))
 (##sys#update-errno)
 (##sys#signal-hook #:process-error 'process-io-close
   can not close fd input port fdr) )
  (if oclosed
   (receive (p f s) (process-wait-for-pid pid) s)
   (receive (p f s) (process-test-pid pid)
  (when (eqv? p pid)
(set! oclosed #t)
(when (eq? -1 (file-close-fd! fdw))
   (##sys#update-errno)
   (##sys#signal-hook #:process-error 
'process-io-close
  can not close fd output 
port fdw) ) s)))
) ) ) ]
 [out
  (let-location
   ((again bool #f))
   (make-output-port
(lambda (s)
  (define start-time (current-milliseconds))
  (let loop ([len (##sys#size s)]
 [off 0])
(if oclosed
(##sys#signal-hook
 #:process-error 'process-io-write fd output port is 
closed fdw)
(let ([n ((foreign-lambda*
   int
   ((int fd) (scheme-pointer buf) (int 
off) (int count) ((c-pointer bool) again))

Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

On Sep 30 2011, Jörg F. Wittenberger wrote:


Alan,

I figured that you did almost have you for the process-io-ports code
I cited the other day.


Alan, another warning:  I just fixed a case of EINTR, where the code
shows strong heritage from the tcp unit.  (I wrote some parallel code
base on it, because the API did not fit my needs.  At the low level the
code is written, establishing a signal handler around each call just to
catch the highly probable -1 exception would have made a mess out of it.
Therefore I'm calling the accept(2) etc. via Chicken's FFI and handle all
the results in one place.)

Nevertheless, the basic structure of the code is the same.  So I'm afraid
that there are more occurrences of unhandled EINTR in the tcp unit.
So if your code depends on it, be prepared.

/Jörg





___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

On Sep 30 2011, Alan Post wrote:


Thank you for this.

I notice, right away, that your io_needs_restart handles EAGAIN in
the same way it handles EINTR.  I have always introduced a timeout
when I get an EAGAIN, and I give up after say 3 tries.


While I can follow the reasoning, it might not (or may?) apply in
the case at hand.

The select(2) call will not be restarted right away.
First the signal handlers will be run.  Those might change the
set of fd's in the set of ongoing i/o.
Alternatively those might have unblocked handler threads.
The Scheduler will run them before it retries.
Next it will try the timeout queue.  Though since we've been unblocked
for a different reason, this is probably not due (except if it took
long enough to run the signal handlers.

At worst nothing has changed.  Then, after giving one time slice to
all threads which are ready, the select is restarted.  Using a new timeout.

IMHO this level of dealing with i/o should not at all impose any wild
guess of timeouts.

Iff the i/o was interrupted, then try to schedule the close(fd) before
the next retry (the scheduler can't help in case the client thread refuses
to close the fd, but it will defend: next time this is going to be a BADFD
and it is free to signal an exception in the thread).


NB: At higher level I usually have a timeout/retry loop with exponential
back off.




___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-30 Thread Jörg F . Wittenberger

There is one thing about the modified signaling:
I now can better see from the signal handler what all the thread
states are.

The bad (good actually, wild guesses before) news: it *is* possible
to end up with the current thread state as blocked.

However I just found out, and the thread which is in this state comes
from some very unclean code written these days along the lines
with those signal experiments.  Could be that I just have to remove
that code.  Maybe it's worse.

/Jörg



___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread John Cowan
Alan Post scripsit:

 It used to be one tested for sigaction in the same way you might
 test for other features.  I'm not sure if chicken runs on a
 platform that doesn't have sigaction--do I need to add a feature
 test for this and preserve the existing capability on platforms
 without sigaction?

Win32 systems (not including Cygwin) have signal() but not sigaction().
The only signals on Win32 are SIGABRT, SIGFPE, and SIGSEGV.  SIGILL and
SIGTERM can be trapped, but they can only happen if you raise them
yourself with raise().  SIGINT can also be trapped, but that's a bad
idea, because the handler will be run on a separate Win32 thread.

All of our other hosts implement sigaction().

-- 
But the next day there came no dawn,John Cowan
and the Grey Company passed on into the co...@ccil.org
darkness of the Storm of Mordor and werehttp://www.ccil.org/~cowan
lost to mortal sight; but the Dead
followed them.  --The Passing of the Grey Company

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Alan Post
On Thu, Sep 29, 2011 at 10:44:42AM -0400, John Cowan wrote:
 Alan Post scripsit:
 
  It used to be one tested for sigaction in the same way you might
  test for other features.  I'm not sure if chicken runs on a
  platform that doesn't have sigaction--do I need to add a feature
  test for this and preserve the existing capability on platforms
  without sigaction?
 
 Win32 systems (not including Cygwin) have signal() but not sigaction().
 The only signals on Win32 are SIGABRT, SIGFPE, and SIGSEGV.  SIGILL and
 SIGTERM can be trapped, but they can only happen if you raise them
 yourself with raise().  SIGINT can also be trapped, but that's a bad
 idea, because the handler will be run on a separate Win32 thread.
 
 All of our other hosts implement sigaction().
 

I'm very happy you had this information to hand--I had not quite
remembered how the signal() interface survived C ANSI-fication
and you just laid it out for me.

Does the ANSI C behavior specify that a signal must be re-registered
after it is called?  Is it more reliable for me to follow the ANSI
C standard or the w32 documentation on this interface?  If w32,
where do I find that?

I will submit a new patch that includes a feature test so this code
will work on w32.

.i.ioki'edo mu'o mi'e .alyn.
-- 
.i ma'a lo bradi cu penmi gi'e du

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Jörg F . Wittenberger

On Sep 29 2011, John Cowan wrote:


Alan Post scripsit:


It used to be one tested for sigaction in the same way you might
test for other features.  I'm not sure if chicken runs on a
platform that doesn't have sigaction--do I need to add a feature
test for this and preserve the existing capability on platforms
without sigaction?


Win32 systems (not including Cygwin) have signal() but not sigaction().
The only signals on Win32 are SIGABRT, SIGFPE, and SIGSEGV.  SIGILL and
SIGTERM can be trapped, but they can only happen if you raise them
yourself with raise().  SIGINT can also be trapped, but that's a bad
idea, because the handler will be run on a separate Win32 thread.


Too bad.  I forgot.  It's been quite a while that I considered Win32.

Could we live with a conditional compilation here?  (I'm *not* sure.
It complicates thing quite a lot.  Let alone readability of the source.)





___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Jörg F . Wittenberger

Here an interesting finding:

On Sep 29 2011, Alan Post wrote:


This patch replaces signal with sigaction for registering signals.
sigaction is a newer API for signal processing that fixes some
deficiencies of the original signal API.  One fix can be seen in
this patch: we don't have to reregister the signal handler after
a signal is sent.

That prevents a race condition whereby a signal is delivered, our
signal handler is reset, and before we can reregister our signal
handler, another signal is sent (which we then miss).


Since I'm quite old school I've been used to the meaning of signals
to be almost reliable.  Except under arbitrary complex usage
restrictions.

Hence I rarely ever tried to count signals, but use them as a hint,
which operation would be in order.

This might have been not enough!

Turn out that with your patch applied something changed:
I had one usage case, which almost sure (say ~50%+-25%) would run
into that eat-all-memory condition.  I tried too often, I fail to
reproduce the condition.

However at this time I can't convince myself that this is not a false
positive.  :-/




___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Alan Post
On Thu, Sep 29, 2011 at 05:45:46PM +0200, Jörg F. Wittenberger wrote:
 Here an interesting finding:
 
 On Sep 29 2011, Alan Post wrote:
 
 This patch replaces signal with sigaction for registering signals.
 sigaction is a newer API for signal processing that fixes some
 deficiencies of the original signal API.  One fix can be seen in
 this patch: we don't have to reregister the signal handler after
 a signal is sent.
 
 That prevents a race condition whereby a signal is delivered, our
 signal handler is reset, and before we can reregister our signal
 handler, another signal is sent (which we then miss).
 
 Since I'm quite old school I've been used to the meaning of signals
 to be almost reliable.  Except under arbitrary complex usage
 restrictions.
 
 Hence I rarely ever tried to count signals, but use them as a hint,
 which operation would be in order.
 
 This might have been not enough!
 
 Turn out that with your patch applied something changed:
 I had one usage case, which almost sure (say ~50%+-25%) would run
 into that eat-all-memory condition.  I tried too often, I fail to
 reproduce the condition.
 
 However at this time I can't convince myself that this is not a false
 positive.  :-/
 

Even with my patch, there is still a bug in the chicken signal
handler:

void global_signal_handler(int signum)
{
  C_raise_interrupt(signal_mapping_table[ signum ]);
}

This signal handler will notify the main thread that signal X has
been raised, but it doesn't keep track of how often that happens.

By the time we get around to handling this signal, it could have
been raised more than once, and we only fire our signal handler
once regardless of how many signals were delivered between the
original interrupt and executing the deferred handler.

If you're doing anything at all that is reasonably interrupt
heavy, you're going to be seeing this behavior.  The quick test
would be to fork a few hundred children (that all immediately
exit) all at once and count the number of times SIGCHLD is raised.

I haven't written this test yet, it's my next test case to follow
my EINTR test--though I suspect you'll get fewer SIGCHLD interrupts
than you had spawned children.

I also suspect there is a condition here where the signal handler
flags the interrupt to be raised, but we're already servicing the
deferred signal, and it goes ahead and resets the
signal_mapping_table before the signal currently being raised is
handled by deferral.  If you're coping with unreliable delivery
from the above method, maybe you're seeing this case instead, which
would be a different class of behavior.

Rather than 1 or more deferred signals being delivered for N signals
raised, you might well see 0 under this condition--If this can happen
at all.  I'm assuming it can, looking at the code, but haven't
verified yet.

-Alan
-- 
.i ma'a lo bradi cu penmi gi'e du

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Alan Post
On Thu, Sep 29, 2011 at 02:15:29PM -0400, John Cowan wrote:
 Alan Post scripsit:
 
  Does the ANSI C behavior specify that a signal must be re-registered
  after it is called?  Is it more reliable for me to follow the ANSI
  C standard or the w32 documentation on this interface?  If w32,
  where do I find that?
 
 The Woe32 documentation is silent about such fine points: the interface
 probably dates back to Windows 3 or even MS-DOS.  For future reference, it's
 at http://msdn.microsoft.com/en-us/library/634ca0c2.aspx .
 

Before the specified function is executed, the value of func is set
to SIG_DFL. The next interrupt signal is treated as described for
SIG_DFL, unless an intervening call to signal specifies otherwise.
This feature lets you reset signals in the called function.

That's good enough (well not really *good*, but *enough*) to know
how to implement signal handling on missing-sigaction platforms.

Thank you,

-Alan
-- 
.i ma'a lo bradi cu penmi gi'e du

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread John Cowan
Alan Post scripsit:

 That's good enough (well not really *good*, but *enough*) to know
 how to implement signal handling on missing-sigaction platforms.

You're right.  Note also, however:

For floating-point exceptions, the value of func is not reset upon receiving 
the signal.

-- 
John Cowan  co...@ccil.org  http://www.ccil.org/~cowan
Thor Heyerdahl recounts his attempt to prove Rudyard Kipling's theory
that the mongoose first came to India on a raft from Polynesia.
--blurb for Rikki-Kon-Tiki-Tavi

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] replace signal with sigaction

2011-09-29 Thread Alan Post
On Thu, Sep 29, 2011 at 07:25:31AM -0600, Alan Post wrote:
 This patch replaces signal with sigaction for registering signals.
 sigaction is a newer API for signal processing that fixes some
 deficiencies of the original signal API.  One fix can be seen in
 this patch: we don't have to reregister the signal handler after
 a signal is sent.
 
 That prevents a race condition whereby a signal is delivered, our
 signal handler is reset, and before we can reregister our signal
 handler, another signal is sent (which we then miss).
 
 I'm not sure even signal() behaves this way these days.
 
 It used to be one tested for sigaction in the same way you might
 test for other features.  I'm not sure if chicken runs on a
 platform that doesn't have sigaction--do I need to add a feature
 test for this and preserve the existing capability on platforms
 without sigaction?
 
 -Alan
 

I have ammended this patch to include a HAVE_SIGACTION define,
to preserve the existing functionality on w32 systems.

diff --git a/Makefile.bsd b/Makefile.bsd
index 5eab203..98e44fd 100644
--- a/Makefile.bsd
+++ b/Makefile.bsd
@@ -83,6 +83,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/Makefile.cygwin b/Makefile.cygwin
index f56bc29..cee6e74 100644
--- a/Makefile.cygwin
+++ b/Makefile.cygwin
@@ -95,6 +95,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/Makefile.haiku b/Makefile.haiku
index 1f86bc3..54634a2 100644
--- a/Makefile.haiku
+++ b/Makefile.haiku
@@ -71,6 +71,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/Makefile.linux b/Makefile.linux
index c713b45..6e5116a 100644
--- a/Makefile.linux
+++ b/Makefile.linux
@@ -72,6 +72,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/Makefile.macosx b/Makefile.macosx
index b4a44d9..da612a4 100644
--- a/Makefile.macosx
+++ b/Makefile.macosx
@@ -96,6 +96,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/Makefile.solaris b/Makefile.solaris
index f2d4dee..84dc433 100644
--- a/Makefile.solaris
+++ b/Makefile.solaris
@@ -102,6 +102,7 @@ chicken-config.h: chicken-defaults.h
echo #define HAVE_LONG_LONG 1 $@
echo #define HAVE_MEMMOVE 1 $@
echo #define HAVE_MEMORY_H 1 $@
+   echo #define HAVE_SIGACTION 1 $@
echo #define HAVE_STDINT_H 1 $@
echo #define HAVE_STDLIB_H 1 $@
echo #define HAVE_STRERROR 1 $@
diff --git a/chicken.h b/chicken.h
index 1739fb9..a154fbe 100644
--- a/chicken.h
+++ b/chicken.h
@@ -859,7 +859,11 @@ DECL_C_PROC_p0 (128,  1,0,0,0,0,0,0,0)
 # define C_isatty   isatty
 # define C_fileno   fileno
 # define C_select   select
+# if defined(HAVE_SIGACTION)
+# define C_sigactionsigaction
+# else
 # define C_signal   signal
+# endif
 # define C_getrusagegetrusage
 # define C_tolower  tolower
 # define C_toupper  toupper
diff --git a/runtime.c b/runtime.c
index 980f303..68e3c90 100644
--- a/runtime.c
+++ b/runtime.c
@@ -982,7 +982,9 @@ void initialize_symbol_table(void)
 void global_signal_handler(int signum)
 {
   C_raise_interrupt(signal_mapping_table[ signum ]);
+#if !defined(HAVE_SIGACTION)
   signal(signum, global_signal_handler);
+#endif
 }
 
 
@@ -4259,11 +4261,28 @@ C_regparm void C_fcall C_raise_interrupt(int reason)
 C_regparm C_word C_fcall C_establish_signal_handler(C_word signum, C_word 
reason)
 {
   int sig = C_unfix(signum);
+#if defined(HAVE_SIGACTION)
+  struct sigaction new, old;
 
-  if(reason == C_SCHEME_FALSE) C_signal(sig, SIG_IGN);
-  else {
+  new.sa_flags = 0;
+