2011-10-29 00:52:24 -04:00
|
|
|
! Copyright (C) 2008, 2011 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2011-10-29 00:52:24 -04:00
|
|
|
USING: system kernel namespaces strings hashtables sequences
|
2011-11-02 14:23:41 -04:00
|
|
|
assocs combinators vocabs init threads continuations math
|
2011-10-29 00:52:24 -04:00
|
|
|
accessors concurrency.flags destructors environment fry io
|
|
|
|
io.encodings.ascii io.backend io.timeouts io.pipes
|
|
|
|
io.pipes.private io.encodings io.encodings.utf8
|
|
|
|
io.streams.duplex io.ports debugger prettyprint summary calendar ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: io.launcher
|
|
|
|
|
2008-04-02 22:27:49 -04:00
|
|
|
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
|
2011-10-29 05:47:10 -04:00
|
|
|
group
|
2008-03-24 19:02:39 -04:00
|
|
|
|
2008-03-06 21:44:52 -05:00
|
|
|
timeout
|
|
|
|
|
|
|
|
handle status
|
2011-10-29 00:52:24 -04:00
|
|
|
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 ;
|
|
|
|
|
|
|
|
: <appender> ( path -- appender ) appender boa ;
|
|
|
|
|
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
|
|
|
|
2011-10-29 05:47:10 -04:00
|
|
|
SYMBOL: +same-group+
|
|
|
|
SYMBOL: +new-group+
|
|
|
|
SYMBOL: +new-session+
|
|
|
|
|
2008-03-06 21:44:52 -05:00
|
|
|
: <process> ( -- process )
|
2008-04-13 16:06:27 -04:00
|
|
|
process new
|
2008-03-06 21:44:52 -05:00
|
|
|
H{ } clone >>environment
|
2011-10-29 05:47:10 -04:00
|
|
|
+append-environment+ >>environment-mode
|
|
|
|
+same-group+ >>group ;
|
2008-03-06 21:44:52 -05:00
|
|
|
|
|
|
|
: process-started? ( process -- ? )
|
|
|
|
dup handle>> swap status>> or ;
|
|
|
|
|
|
|
|
: process-running? ( process -- ? )
|
2008-08-29 11:27:31 -04:00
|
|
|
handle>> >boolean ;
|
2008-03-06 21:44:52 -05:00
|
|
|
|
2008-01-24 03:19:15 -05:00
|
|
|
! Non-blocking process exit notification facility
|
|
|
|
SYMBOL: processes
|
|
|
|
|
2008-04-05 05:26:58 -04:00
|
|
|
HOOK: wait-for-processes io-backend ( -- ? )
|
2008-01-24 03:19:15 -05:00
|
|
|
|
2008-04-05 05:26:58 -04:00
|
|
|
SYMBOL: wait-flag
|
|
|
|
|
|
|
|
: wait-loop ( -- )
|
|
|
|
processes get assoc-empty?
|
|
|
|
[ wait-flag get-global lower-flag ]
|
2008-11-19 02:50:05 -05:00
|
|
|
[ wait-for-processes [ 100 milliseconds sleep ] when ] if ;
|
2008-04-05 05:26:58 -04:00
|
|
|
|
|
|
|
: 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
|
2009-10-19 22:17:02 -04:00
|
|
|
] "io.launcher" add-startup-hook
|
2008-01-24 03:19:15 -05:00
|
|
|
|
2008-03-06 21:44:52 -05:00
|
|
|
: process-started ( process handle -- )
|
|
|
|
>>handle
|
2008-04-05 05:26:58 -04:00
|
|
|
V{ } clone swap processes get set-at
|
|
|
|
wait-flag get-global raise-flag ;
|
2008-01-24 02:27:15 -05:00
|
|
|
|
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-04-13 23:58:07 -04:00
|
|
|
{ +prepend-environment+ [ os-envs assoc-union ] }
|
|
|
|
{ +append-environment+ [ os-envs swap assoc-union ] }
|
2008-02-05 18:33:36 -05:00
|
|
|
{ +replace-environment+ [ ] }
|
2007-11-13 01:10:26 -05:00
|
|
|
} 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 )
|
|
|
|
|
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
|
|
|
|
dup process-started? [
|
2008-08-29 11:27:31 -04:00
|
|
|
process-already-started
|
2008-03-06 21:44:52 -05:00
|
|
|
] when
|
|
|
|
clone ;
|
|
|
|
|
|
|
|
M: object >process <process> swap >>command ;
|
2007-11-12 23:18:42 -05:00
|
|
|
|
2008-02-15 00:29:06 -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
|
|
|
|
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>> . ;
|
|
|
|
|
2010-01-22 13:20:37 -05:00
|
|
|
: (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
|
|
|
|
dup killed>> [ process-was-killed ] [ status>> ] if ;
|
2010-01-22 13:20:37 -05:00
|
|
|
|
|
|
|
: wait-for-process ( process -- status )
|
|
|
|
[ (wait-for-process) ] with-timeout ;
|
2007-11-12 23:18:42 -05:00
|
|
|
|
2008-01-31 00:16:20 -05:00
|
|
|
: run-detached ( desc -- process )
|
2011-10-29 00:52:24 -04:00
|
|
|
>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 ;
|
2008-01-24 02:27:15 -05:00
|
|
|
|
2011-10-31 14:53:07 -04:00
|
|
|
ERROR: process-failed process ;
|
2008-06-15 03:37:37 -04:00
|
|
|
|
|
|
|
M: process-failed error.
|
2011-10-31 14:53:07 -04:00
|
|
|
[
|
|
|
|
"Process exited with error code " write process>> status>> . nl
|
|
|
|
"Launch descriptor:" print nl
|
|
|
|
] [ process>> . ] bi ;
|
2008-02-08 22:15:29 -05:00
|
|
|
|
2008-09-18 19:20:26 -04:00
|
|
|
: wait-for-success ( process -- )
|
2011-10-31 14:53:07 -04:00
|
|
|
dup wait-for-process 0 =
|
|
|
|
[ drop ] [ process-failed ] if ;
|
2008-02-08 22:15:29 -05:00
|
|
|
|
2008-09-18 19:20:26 -04:00
|
|
|
: try-process ( desc -- )
|
|
|
|
run-process wait-for-success ;
|
|
|
|
|
2011-10-29 05:47:10 -04:00
|
|
|
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
|
2011-10-29 00:52:24 -04:00
|
|
|
[ pipe>> [ dispose ] when* ]
|
2011-10-29 05:47:10 -04:00
|
|
|
[ 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
|
|
|
|
2011-10-29 00:52:24 -04:00
|
|
|
M: process set-timeout timeout<< ;
|
2008-02-09 22:56:50 -05:00
|
|
|
|
2008-05-21 02:36:30 -04:00
|
|
|
M: process cancel-operation kill-process ;
|
2008-02-09 22:34:42 -05:00
|
|
|
|
2008-05-06 22:23:18 -04:00
|
|
|
M: object run-pipeline-element
|
|
|
|
[ >process swap >>stdout swap >>stdin run-detached ]
|
2008-05-15 00:23:12 -04:00
|
|
|
[ drop [ [ dispose ] when* ] bi@ ]
|
2008-05-06 22:23:18 -04:00
|
|
|
3bi
|
|
|
|
wait-for-process ;
|
2008-05-05 04:15:24 -04:00
|
|
|
|
2011-10-29 00:52:24 -04:00
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: <process-with-pipe> ( desc -- process pipe )
|
|
|
|
>process (pipe) |dispose [ >>pipe ] keep ;
|
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
2008-09-18 19:20:26 -04:00
|
|
|
: <process-reader*> ( desc encoding -- stream process )
|
2008-05-05 03:19:25 -04:00
|
|
|
[
|
2008-11-30 14:46:39 -05:00
|
|
|
[
|
2011-10-29 00:52:24 -04:00
|
|
|
<process-with-pipe> {
|
|
|
|
[ '[ _ out>> or ] change-stdout ]
|
|
|
|
[ drop run-detached ]
|
2008-11-30 14:46:39 -05:00
|
|
|
[ out>> dispose ]
|
|
|
|
[ in>> <input-port> ]
|
|
|
|
} cleave
|
|
|
|
] dip <decoder> swap
|
2008-05-05 03:19:25 -04:00
|
|
|
] with-destructors ;
|
|
|
|
|
|
|
|
: <process-reader> ( desc encoding -- stream )
|
2008-09-18 19:20:26 -04:00
|
|
|
<process-reader*> drop ; inline
|
2008-05-05 03:19:25 -04:00
|
|
|
|
2008-09-18 19:20:26 -04:00
|
|
|
: with-process-reader ( desc encoding quot -- )
|
|
|
|
[ <process-reader*> ] dip
|
|
|
|
swap [ with-input-stream ] dip
|
|
|
|
wait-for-success ; inline
|
|
|
|
|
|
|
|
: <process-writer*> ( desc encoding -- stream process )
|
2008-05-05 03:19:25 -04:00
|
|
|
[
|
2008-11-30 14:46:39 -05:00
|
|
|
[
|
2011-10-29 00:52:24 -04:00
|
|
|
<process-with-pipe> {
|
|
|
|
[ '[ _ in>> or ] change-stdin ]
|
|
|
|
[ drop run-detached ]
|
2008-11-30 14:46:39 -05:00
|
|
|
[ in>> dispose ]
|
|
|
|
[ out>> <output-port> ]
|
|
|
|
} cleave
|
|
|
|
] dip <encoder> swap
|
2008-05-05 03:19:25 -04:00
|
|
|
] with-destructors ;
|
|
|
|
|
|
|
|
: <process-writer> ( desc encoding -- stream )
|
2008-09-18 19:20:26 -04:00
|
|
|
<process-writer*> drop ; inline
|
|
|
|
|
|
|
|
: with-process-writer ( desc encoding quot -- )
|
|
|
|
[ <process-writer*> ] dip
|
|
|
|
swap [ with-output-stream ] dip
|
|
|
|
wait-for-success ; inline
|
2008-05-05 03:19:25 -04:00
|
|
|
|
2008-09-18 19:20:26 -04:00
|
|
|
: <process-stream*> ( desc encoding -- stream process )
|
2008-05-05 03:19:25 -04:00
|
|
|
[
|
2008-11-30 14:46:39 -05:00
|
|
|
[
|
|
|
|
(pipe) (pipe) {
|
|
|
|
[ [ |dispose drop ] bi@ ]
|
|
|
|
[
|
|
|
|
rot >process
|
|
|
|
[ swap in>> or ] change-stdin
|
|
|
|
[ swap out>> or ] change-stdout
|
|
|
|
run-detached
|
|
|
|
]
|
|
|
|
[ [ out>> dispose ] [ in>> dispose ] bi* ]
|
|
|
|
[ [ in>> <input-port> ] [ out>> <output-port> ] bi* ]
|
|
|
|
} 2cleave
|
|
|
|
] dip <encoder-duplex> swap
|
2008-05-05 03:19:25 -04:00
|
|
|
] with-destructors ;
|
2007-11-12 23:18:42 -05:00
|
|
|
|
2008-02-21 16:22:49 -05:00
|
|
|
: <process-stream> ( desc encoding -- stream )
|
2008-09-18 19:20:26 -04:00
|
|
|
<process-stream*> drop ; inline
|
|
|
|
|
|
|
|
: with-process-stream ( desc encoding quot -- )
|
|
|
|
[ <process-stream*> ] dip
|
|
|
|
swap [ with-stream ] dip
|
|
|
|
wait-for-success ; inline
|
2008-01-24 03:19:15 -05:00
|
|
|
|
2009-05-12 06:16:19 -04:00
|
|
|
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
|
2009-05-12 06:16:19 -04:00
|
|
|
utf8 <process-reader*>
|
2010-01-22 13:20:37 -05:00
|
|
|
[ [ stream-contents ] [ dup (wait-for-process) ] bi* ] with-timeout
|
2009-05-12 06:16:19 -04:00
|
|
|
0 = [ 2drop ] [ output-process-error ] if ;
|
|
|
|
|
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
|
|
|
|
2008-07-02 22:52:28 -04:00
|
|
|
{
|
2008-12-14 21:03:00 -05:00
|
|
|
{ [ os unix? ] [ "io.launcher.unix" require ] }
|
2010-09-19 15:02:32 -04:00
|
|
|
{ [ os windows? ] [ "io.launcher.windows" require ] }
|
2008-07-02 22:52:28 -04:00
|
|
|
[ ]
|
|
|
|
} cond
|