new module unix.signals: app-level signal handlers
example:
IN: scratchpad USING: unix.ffi unix.signals ;
Loading resource:basis/unix/signals/signals.factor
IN: scratchpad [ V{ "Me not that kind of orc!" "Me busy, leave me alone!" "Work work" "Zug zug" } pop print flush ] SIGINFO add-signal-handler
IN: scratchpad load: 0.60  cmd: factor 41541 running 0.28u 0.16s
Zug zug
load: 0.71  cmd: factor 41541 running 0.28u 0.16s
Work work
load: 0.71  cmd: factor 41541 running 0.28u 0.16s
Me busy, leave me alone!
load: 0.73  cmd: factor 41541 running 0.28u 0.16s
Me not that kind of orc!
			
			
				db4
			
			
		
							parent
							
								
									0c58fd5c26
								
							
						
					
					
						commit
						fc7c175c9f
					
				| 
						 | 
				
			
			@ -187,12 +187,23 @@ M: stdin cancel-operation
 | 
			
		|||
        size-read-fd <fd> init-fd <input-port> >>size
 | 
			
		||||
        data-read-fd <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 [ <fd> init-fd <input-port>
 | 
			
		||||
        '[ [ 4 _ io:stream-read ] loop ] "Signals" spawn drop
 | 
			
		||||
    signal-pipe-fd [
 | 
			
		||||
        <fd> init-fd <input-port>
 | 
			
		||||
        '[ _ signal-pipe-loop ] "Signals" spawn drop
 | 
			
		||||
    ] when* ;
 | 
			
		||||
 | 
			
		||||
M: unix init-stdio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
! (c)2011 Joe Groff bsd license
 | 
			
		||||
USING: assocs io.backend.unix kernel namespaces sequences
 | 
			
		||||
threads ;
 | 
			
		||||
IN: unix.signals
 | 
			
		||||
 | 
			
		||||
<PRIVATE
 | 
			
		||||
 | 
			
		||||
SYMBOL: signal-handlers
 | 
			
		||||
 | 
			
		||||
signal-handlers [ H{ } ] initialize
 | 
			
		||||
 | 
			
		||||
PRIVATE>
 | 
			
		||||
 | 
			
		||||
: 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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue