diff --git a/basis/io/backend/unix/unix.factor b/basis/io/backend/unix/unix.factor index 37dc40bcca..8c01479574 100755 --- a/basis/io/backend/unix/unix.factor +++ b/basis/io/backend/unix/unix.factor @@ -187,12 +187,23 @@ M: stdin cancel-operation size-read-fd init-fd >>size data-read-fd >>data ; +SYMBOL: dispatch-signal-hook + +dispatch-signal-hook [ [ drop ] ] initialize + : signal-pipe-fd ( -- n ) OBJ-SIGNAL-PIPE special-object ; inline +: signal-pipe-loop ( port -- ) + '[ + int heap-size _ io:stream-read + dup [ int deref dispatch-signal-hook get call( x -- ) ] when* + ] loop ; + : start-signal-pipe-thread ( -- ) - signal-pipe-fd [ init-fd - '[ [ 4 _ io:stream-read ] loop ] "Signals" spawn drop + signal-pipe-fd [ + init-fd + '[ _ signal-pipe-loop ] "Signals" spawn drop ] when* ; M: unix init-stdio diff --git a/basis/unix/ffi/ffi.factor b/basis/unix/ffi/ffi.factor index 6798bb1307..721efc921b 100644 --- a/basis/unix/ffi/ffi.factor +++ b/basis/unix/ffi/ffi.factor @@ -168,4 +168,7 @@ FUNCTION: int unlink ( c-string path ) ; FUNCTION: int utimes ( c-string path, timeval[2] times ) ; FUNCTION: ssize_t write ( int fd, void* buf, size_t nbytes ) ; +FUNCTION: int kill ( pid_t pid, int signal ) ; +FUNCTION: int raise ( int signal ) ; + "librt" "librt.so" cdecl add-library diff --git a/basis/unix/signals/signals-tests.factor b/basis/unix/signals/signals-tests.factor new file mode 100644 index 0000000000..7b57e4994f --- /dev/null +++ b/basis/unix/signals/signals-tests.factor @@ -0,0 +1,34 @@ +USING: calendar continuations io kernel math namespaces threads +tools.test unix.ffi unix.signals ; +IN: unix.signals.tests + +SYMBOL: sigusr1-count +0 sigusr1-count set-global + +CONSTANT: test-sigusr1-handler [ 1 sigusr1-count +@ ] + +"=========" print +"NOTE: This test uses SIGUSR1. It may break or cause unwanted behavior" print +"if other SIGUSR1 handlers are installed." print +"=========" print flush + +test-sigusr1-handler SIGUSR1 add-signal-handler +[ + + [ 1 ] [ + sigusr1-count get-global + SIGUSR1 raise drop + 0.5 seconds sleep + sigusr1-count get-global + swap - + ] unit-test + +] [ test-sigusr1-handler SIGUSR1 remove-signal-handler ] [ ] cleanup + +[ 0 ] [ + sigusr1-count get-global + SIGUSR1 raise drop + 0.5 seconds sleep + sigusr1-count get-global swap - +] unit-test + diff --git a/basis/unix/signals/signals.factor b/basis/unix/signals/signals.factor new file mode 100644 index 0000000000..76e392a32e --- /dev/null +++ b/basis/unix/signals/signals.factor @@ -0,0 +1,23 @@ +! (c)2011 Joe Groff bsd license +USING: assocs io.backend.unix kernel namespaces sequences +threads ; +IN: unix.signals + + + +: dispatch-signal ( sig -- ) + signal-handlers get-global at [ in-thread ] each ; + +: add-signal-handler ( handler: ( -- ) sig -- ) + signal-handlers get-global push-at ; + +: remove-signal-handler ( handler sig -- ) + signal-handlers get-global at [ remove! drop ] [ drop ] if* ; + +[ dispatch-signal ] dispatch-signal-hook set-global diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index f953751799..d5b4ea90a4 100755 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -318,6 +318,12 @@ void factor_vm::unix_init_signals() init_sigaction_with_handler(&enqueue_sigaction, enqueue_signal_handler); sigaction_safe(SIGWINCH,&enqueue_sigaction,NULL); + sigaction_safe(SIGUSR1,&enqueue_sigaction,NULL); + sigaction_safe(SIGCONT,&enqueue_sigaction,NULL); + sigaction_safe(SIGURG,&enqueue_sigaction,NULL); + sigaction_safe(SIGIO,&enqueue_sigaction,NULL); + sigaction_safe(SIGPROF,&enqueue_sigaction,NULL); + sigaction_safe(SIGVTALRM,&enqueue_sigaction,NULL); #ifdef SIGINFO sigaction_safe(SIGINFO,&enqueue_sigaction,NULL); #endif