factor/basis/io/launcher/launcher.factor

309 lines
7.4 KiB
Factor
Raw Normal View History

! Copyright (C) 2008, 2011 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs calendar combinators concurrency.flags
debugger destructors environment fry init io io.backend
io.encodings io.encodings.utf8 io.pipes io.pipes.private
io.ports io.streams.duplex io.timeouts kernel namespaces
prettyprint sequences strings system threads vocabs ;
2007-09-20 18:09:08 -04:00
IN: io.launcher
TUPLE: process < identity-tuple
2008-03-06 21:44:52 -05:00
command
detached
environment
environment-mode
stdin
stdout
stderr
2008-03-24 19:02:39 -04:00
priority
group
2008-03-24 19:02:39 -04:00
2008-03-06 21:44:52 -05:00
timeout
handle status
killed
pipe ;
2008-03-06 21:44:52 -05:00
SYMBOL: +closed+
SYMBOL: +stdout+
2008-05-05 20:12:22 -04:00
TUPLE: appender path ;
C: <appender> appender
2008-05-05 20:12:22 -04:00
2008-03-06 21:44:52 -05:00
SYMBOL: +prepend-environment+
SYMBOL: +replace-environment+
SYMBOL: +append-environment+
2008-03-24 19:02:39 -04:00
SYMBOL: +lowest-priority+
SYMBOL: +low-priority+
SYMBOL: +normal-priority+
SYMBOL: +high-priority+
SYMBOL: +highest-priority+
2008-03-26 16:55:55 -04:00
SYMBOL: +realtime-priority+
2008-03-24 19:02:39 -04:00
SYMBOL: +same-group+
SYMBOL: +new-group+
SYMBOL: +new-session+
2008-03-06 21:44:52 -05:00
: <process> ( -- process )
process new
H{ } clone >>environment
+append-environment+ >>environment-mode
+same-group+ >>group ;
2008-03-06 21:44:52 -05:00
: process-started? ( process -- ? )
2014-11-30 22:26:23 -05:00
[ handle>> ] [ status>> ] bi or ;
2008-03-06 21:44:52 -05:00
: process-running? ( process -- ? )
2008-08-29 11:27:31 -04:00
handle>> >boolean ;
2008-03-06 21:44:52 -05:00
! Non-blocking process exit notification facility
SYMBOL: processes
HOOK: (wait-for-processes) io-backend ( -- ? )
<PRIVATE
SYMBOL: wait-flag
: wait-loop ( -- )
processes get assoc-empty?
[ wait-flag get-global lower-flag ]
[ (wait-for-processes) [ 100 milliseconds sleep ] when ] if ;
: start-wait-thread ( -- )
<flag> wait-flag set-global
[ wait-loop t ] "Process wait" spawn-server drop ;
2008-10-19 05:40:15 -04:00
[
H{ } clone processes set-global
start-wait-thread
] "io.launcher" add-startup-hook
2008-03-06 21:44:52 -05:00
: process-started ( process handle -- )
>>handle
V{ } clone swap processes get set-at
wait-flag get-global raise-flag ;
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 )
[ environment>> ] [ environment-mode>> ] bi {
{ +prepend-environment+ [ os-envs assoc-union ] }
{ +append-environment+ [ os-envs swap assoc-union ] }
2008-02-05 18:33:36 -05:00
{ +replace-environment+ [ ] }
} case ;
PRIVATE>
2008-02-09 23:28:22 -05:00
2008-03-06 21:44:52 -05:00
GENERIC: >process ( obj -- process )
2008-09-19 04:10:44 -04:00
ERROR: process-already-started process ;
2008-08-29 11:27:31 -04:00
2008-09-19 04:14:11 -04:00
M: process-already-started error.
"Process has already been started" print nl
"Launch descriptor:" print nl
process>> . ;
2008-08-29 11:27:31 -04:00
2008-03-06 21:44:52 -05:00
M: process >process
2015-08-13 06:20:39 -04:00
dup process-started? [ throw-process-already-started ] when
2008-03-06 21:44:52 -05:00
clone ;
M: object >process <process> swap >>command ;
2007-11-12 23:18:42 -05:00
HOOK: (current-process) io-backend ( -- handle )
2007-11-12 23:18:42 -05:00
2008-09-19 04:10:44 -04:00
ERROR: process-was-killed process ;
2008-08-29 11:27:31 -04:00
2008-09-19 04:14:11 -04:00
M: process-was-killed error.
"Process was killed as a result of a call to" print
"kill-process, or a timeout" print
nl
"Launch descriptor:" print nl
process>> . ;
: (wait-for-process) ( process -- status )
dup handle>>
2010-03-27 12:03:06 -04:00
[ self over processes get at push "process" suspend drop ] when
2015-08-13 09:51:44 -04:00
dup killed>> [ throw-process-was-killed ] [ status>> ] if ;
: wait-for-process ( process -- status )
[ (wait-for-process) ] with-timeout ;
2007-11-12 23:18:42 -05:00
HOOK: (run-process) io-backend ( process -- handle )
2008-01-31 00:16:20 -05:00
: run-detached ( desc -- process )
>process [ dup (run-process) process-started ] keep ;
2008-03-06 21:44:52 -05:00
: run-process ( desc -- process )
run-detached
dup detached>> [ dup wait-for-process drop ] unless ;
ERROR: process-failed process ;
2008-06-15 03:37:37 -04:00
M: process-failed error.
[
"Process exited with error code " write process>> status>> . nl
"Launch descriptor:" print nl
] [ process>> . ] bi ;
2008-02-08 22:15:29 -05:00
: check-success ( process status -- )
2015-08-13 06:20:39 -04:00
0 = [ drop ] [ throw-process-failed ] if ;
2008-09-18 19:20:26 -04:00
: wait-for-success ( process -- )
dup wait-for-process check-success ;
2008-02-08 22:15:29 -05:00
2008-09-18 19:20:26 -04:00
: try-process ( desc -- )
run-process wait-for-success ;
HOOK: (kill-process) io-backend ( process -- )
2008-02-03 15:23:14 -05:00
: kill-process ( process -- )
2008-03-06 21:44:52 -05:00
t >>killed
[ pipe>> [ dispose ] when* ]
[ dup handle>> [ (kill-process) ] [ drop ] if ] bi ;
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 timeout<< ;
2008-02-09 22:56:50 -05:00
M: process cancel-operation kill-process ;
2008-02-09 22:34:42 -05:00
M: object run-pipeline-element
[
>process
swap >>stdout
swap >>stdin
run-detached
] [
[
drop [ [ &dispose drop ] when* ] bi@
] with-destructors
] 3bi wait-for-process ;
2008-05-05 04:15:24 -04:00
<PRIVATE
: <process-with-pipe> ( desc -- process pipe )
>process (pipe) |dispose [ >>pipe ] keep ;
: (process-reader) ( desc encoding -- stream process )
[
[
<process-with-pipe> {
[ '[ _ out>> or ] change-stdout ]
[ drop run-detached ]
[ out>> dispose ]
[ in>> <input-port> ]
} cleave
] dip <decoder> swap
] with-destructors ;
PRIVATE>
: <process-reader> ( desc encoding -- stream )
(process-reader) drop ; inline
2014-12-30 20:23:24 -05:00
: with-process-reader* ( desc encoding quot -- process status )
[ (process-reader) ] dip '[ _ with-input-stream ] dip
dup wait-for-process ; inline
2014-12-30 20:23:24 -05:00
: with-process-reader ( desc encoding quot -- )
with-process-reader* check-success ; inline
2008-09-18 19:20:26 -04:00
<PRIVATE
: (process-writer) ( desc encoding -- stream process )
[
[
<process-with-pipe> {
[ '[ _ in>> or ] change-stdin ]
[ drop run-detached ]
[ in>> dispose ]
[ out>> <output-port> ]
} cleave
] dip <encoder> swap
] with-destructors ;
PRIVATE>
: <process-writer> ( desc encoding -- stream )
(process-writer) drop ; inline
2008-09-18 19:20:26 -04:00
2014-12-30 20:23:24 -05:00
: with-process-writer* ( desc encoding quot -- process status )
[ (process-writer) ] dip '[ _ with-output-stream ] dip
dup wait-for-process ; inline
2014-12-30 20:23:24 -05:00
: with-process-writer ( desc encoding quot -- )
with-process-writer* check-success ; inline
<PRIVATE
: (process-stream) ( desc encoding -- stream process )
[
[
(pipe) |dispose
(pipe) |dispose {
[
rot >process
[ swap in>> or ] change-stdin
[ swap out>> or ] change-stdout
run-detached
]
[ [ out>> &dispose drop ] [ in>> &dispose drop ] bi* ]
[ [ in>> <input-port> ] [ out>> <output-port> ] bi* ]
} 2cleave
] dip <encoder-duplex> swap
] with-destructors ;
2007-11-12 23:18:42 -05:00
PRIVATE>
2008-02-21 16:22:49 -05:00
: <process-stream> ( desc encoding -- stream )
(process-stream) drop ; inline
2008-09-18 19:20:26 -04:00
2014-12-30 20:23:24 -05:00
: with-process-stream* ( desc encoding quot -- process status )
[ (process-stream) ] dip '[ _ with-stream ] dip
dup wait-for-process ; inline
2014-12-30 20:23:24 -05:00
: with-process-stream ( desc encoding quot -- )
with-process-stream* check-success ; inline
ERROR: output-process-error { output string } { process process } ;
M: output-process-error error.
[ "Process:" print process>> . nl ]
[ "Output:" print output>> print ]
bi ;
: try-output-process ( command -- )
>process
+stdout+ >>stderr
2009-05-21 01:08:43 -04:00
[ +closed+ or ] change-stdin
utf8 (process-reader)
[ [ stream-contents ] [ dup (wait-for-process) ] bi* ] with-timeout
2015-08-13 06:20:39 -04:00
0 = [ 2drop ] [ throw-output-process-error ] if ;
<PRIVATE
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
PRIVATE>
2008-07-02 22:52:28 -04:00
{
{ [ os unix? ] [ "io.launcher.unix" require ] }
{ [ os windows? ] [ "io.launcher.windows" require ] }
2008-07-02 22:52:28 -04:00
} cond