factor/extra/io/launcher/launcher.factor

163 lines
3.8 KiB
Factor
Raw Normal View History

! Copyright (C) 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-02-09 22:34:42 -05:00
USING: io io.backend io.timeouts system kernel namespaces
strings hashtables sequences assocs combinators vocabs.loader
init threads continuations math io.encodings io.streams.duplex
2008-03-20 16:30:59 -04:00
io.nonblocking accessors ;
2007-09-20 18:09:08 -04:00
IN: io.launcher
2008-03-06 21:44:52 -05:00
TUPLE: process
command
detached
environment
environment-mode
stdin
stdout
stderr
timeout
handle status
killed ;
SYMBOL: +closed+
SYMBOL: +inherit+
SYMBOL: +stdout+
SYMBOL: +prepend-environment+
SYMBOL: +replace-environment+
SYMBOL: +append-environment+
: <process> ( -- process )
process construct-empty
H{ } clone >>environment
+append-environment+ >>environment-mode ;
: process-started? ( process -- ? )
dup handle>> swap status>> or ;
: process-running? ( process -- ? )
process-handle >boolean ;
! Non-blocking process exit notification facility
SYMBOL: processes
[ H{ } clone processes set-global ] "io.launcher" add-init-hook
HOOK: register-process io-backend ( process -- )
M: object register-process drop ;
2008-03-06 21:44:52 -05:00
: process-started ( process handle -- )
>>handle
V{ } clone over processes get set-at
2008-03-06 21:44:52 -05:00
register-process ;
M: process equal? 2drop f ;
M: process hashcode* process-handle hashcode* ;
2008-03-06 21:44:52 -05:00
: pass-environment? ( process -- ? )
dup environment>> assoc-empty? not
swap environment-mode>> +replace-environment+ eq? or ;
2008-03-04 16:07:57 -05:00
2008-03-06 21:44:52 -05:00
: get-environment ( process -- env )
dup environment>>
swap environment-mode>> {
2008-02-05 18:33:36 -05:00
{ +prepend-environment+ [ os-envs union ] }
{ +append-environment+ [ os-envs swap union ] }
{ +replace-environment+ [ ] }
} case ;
2008-02-09 23:28:22 -05:00
: string-array? ( obj -- ? )
dup sequence? [ [ string? ] all? ] [ drop f ] if ;
2008-03-06 21:44:52 -05:00
GENERIC: >process ( obj -- process )
M: process >process
dup process-started? [
"Process has already been started once" throw
] when
clone ;
M: object >process <process> swap >>command ;
2007-11-12 23:18:42 -05:00
HOOK: current-process-handle io-backend ( -- handle )
2008-03-06 21:44:52 -05:00
HOOK: run-process* io-backend ( process -- handle )
2007-11-12 23:18:42 -05:00
: wait-for-process ( process -- status )
2008-02-09 22:34:42 -05:00
[
2008-03-06 21:44:52 -05:00
dup handle>>
[
dup [ processes get at push ] curry
"process" suspend drop
] when
2008-03-06 21:44:52 -05:00
dup killed>>
[ "Process was killed" throw ] [ status>> ] if
2008-02-09 22:34:42 -05:00
] with-timeout ;
2007-11-12 23:18:42 -05:00
2008-01-31 00:16:20 -05:00
: run-detached ( desc -- process )
2008-03-06 21:44:52 -05:00
>process
dup dup run-process* process-started
dup timeout>> [ over set-timeout ] when* ;
: run-process ( desc -- process )
run-detached
dup detached>> [ dup wait-for-process drop ] unless ;
2008-02-08 22:15:29 -05:00
TUPLE: process-failed code ;
: process-failed ( code -- * )
\ process-failed construct-boa throw ;
2008-02-08 22:15:29 -05:00
2008-03-11 20:51:58 -04:00
: try-process ( desc -- )
2008-02-08 22:15:29 -05:00
run-process wait-for-process dup zero?
[ drop ] [ process-failed ] if ;
2008-02-03 15:23:14 -05:00
HOOK: kill-process* io-backend ( handle -- )
: kill-process ( process -- )
2008-03-06 21:44:52 -05:00
t >>killed
handle>> [ kill-process* ] when* ;
2008-02-03 15:23:14 -05:00
2008-03-06 21:44:52 -05:00
M: process timeout timeout>> ;
2008-02-21 20:12:55 -05:00
M: process set-timeout set-process-timeout ;
2008-02-09 22:56:50 -05:00
2008-02-09 22:34:42 -05:00
M: process timed-out kill-process ;
2008-03-06 21:44:52 -05:00
HOOK: (process-stream) io-backend ( process -- handle in out )
TUPLE: process-stream process ;
2007-11-12 23:18:42 -05:00
2008-02-21 16:22:49 -05:00
: <process-stream> ( desc encoding -- stream )
2008-03-06 21:44:52 -05:00
>r >process dup dup (process-stream)
>r >r process-started process-stream construct-boa
r> r> <reader&writer> r> <encoder-duplex>
over set-delegate ;
: with-process-stream ( desc quot -- status )
swap <process-stream>
[ swap with-stream ] keep
2008-03-06 21:44:52 -05:00
process>> wait-for-process ; inline
2008-03-06 21:44:52 -05:00
: notify-exit ( process status -- )
>>status
2008-02-18 06:07:40 -05:00
[ processes get delete-at* drop [ resume ] each ] keep
2008-03-06 21:44:52 -05:00
f >>handle
drop ;
2008-03-03 18:44:57 -05:00
GENERIC: underlying-handle ( stream -- handle )
M: port underlying-handle port-handle ;
M: duplex-stream underlying-handle
dup duplex-stream-in underlying-handle
swap duplex-stream-out underlying-handle tuck =
[ "Invalid duplex stream" throw ] when ;