Add options to set the child process group id or session for Unix. This fixes part of #307.
parent
dc0a921866
commit
eb7fd4a69b
|
@ -35,6 +35,15 @@ $nl
|
|||
{ "a file stream or a socket - the stream is connected to the given Factor stream, which cannot be used again from within Factor and must be closed after the process has been started" }
|
||||
} ;
|
||||
|
||||
ARTICLE: "io.launcher.group" "Setting process groups"
|
||||
"The process group of a child process can be controlled by setting the " { $snippet "group" } " slot of a " { $link process } " tuple:"
|
||||
{ $list
|
||||
{ $link +same-group+ }
|
||||
{ $link +new-group+ }
|
||||
{ $link +new-session+ }
|
||||
}
|
||||
"The default value is " { $link +same-group+ } ", which denotes that the child process should be part of the process group of the parent process. The " { $link +new-group+ } " option creates a new process group, while the " { $link +new-session+ } " creates a new session." ;
|
||||
|
||||
ARTICLE: "io.launcher.priority" "Setting process priority"
|
||||
"The priority of the child process can be set by storing one of the below symbols in the " { $snippet "priority" } " slot of a " { $link process } " tuple:"
|
||||
{ $list
|
||||
|
@ -126,7 +135,7 @@ HELP: kill-process
|
|||
{ $description "Kills a running process. Does nothing if the process has already exited." } ;
|
||||
|
||||
HELP: kill-process*
|
||||
{ $values { "handle" "a process handle" } }
|
||||
{ $values { "process" "process" } }
|
||||
{ $contract "Kills a running process." }
|
||||
{ $notes "User code should call " { $link kill-process } " instead." } ;
|
||||
|
||||
|
@ -282,6 +291,7 @@ ARTICLE: "io.launcher" "Operating system processes"
|
|||
"io.launcher.detached"
|
||||
"io.launcher.environment"
|
||||
"io.launcher.redirection"
|
||||
"io.launcher.group"
|
||||
"io.launcher.priority"
|
||||
"io.launcher.timeouts"
|
||||
} ;
|
||||
|
|
|
@ -21,6 +21,7 @@ stdout
|
|||
stderr
|
||||
|
||||
priority
|
||||
group
|
||||
|
||||
timeout
|
||||
|
||||
|
@ -47,10 +48,15 @@ SYMBOL: +high-priority+
|
|||
SYMBOL: +highest-priority+
|
||||
SYMBOL: +realtime-priority+
|
||||
|
||||
SYMBOL: +same-group+
|
||||
SYMBOL: +new-group+
|
||||
SYMBOL: +new-session+
|
||||
|
||||
: <process> ( -- process )
|
||||
process new
|
||||
H{ } clone >>environment
|
||||
+append-environment+ >>environment-mode ;
|
||||
+append-environment+ >>environment-mode
|
||||
+same-group+ >>group ;
|
||||
|
||||
: process-started? ( process -- ? )
|
||||
dup handle>> swap status>> or ;
|
||||
|
@ -158,12 +164,12 @@ M: process-failed error.
|
|||
: try-process ( desc -- )
|
||||
run-process wait-for-success ;
|
||||
|
||||
HOOK: kill-process* io-backend ( handle -- )
|
||||
HOOK: kill-process* io-backend ( process -- )
|
||||
|
||||
: kill-process ( process -- )
|
||||
t >>killed
|
||||
[ pipe>> [ dispose ] when* ]
|
||||
[ handle>> [ kill-process* ] when* ] bi ;
|
||||
[ dup handle>> [ kill-process* ] [ drop ] if ] bi ;
|
||||
|
||||
M: process timeout timeout>> ;
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ io.pathnames tools.test io.launcher arrays io namespaces
|
|||
continuations math io.encodings.binary io.encodings.ascii
|
||||
accessors kernel sequences io.encodings.utf8 destructors
|
||||
io.streams.duplex locals concurrency.promises threads
|
||||
unix.process calendar unix unix.process debugger.unix
|
||||
io.timeouts io.launcher.unix ;
|
||||
unix.process calendar unix debugger.unix io.timeouts
|
||||
io.launcher.unix ;
|
||||
|
||||
[ ] [
|
||||
[ "launcher-test-1" temp-file delete-file ] ignore-errors
|
||||
|
@ -158,7 +158,7 @@ io.timeouts io.launcher.unix ;
|
|||
[ p fulfill ] [ wait-for-process s fulfill ] bi
|
||||
] in-thread
|
||||
|
||||
p 1 seconds ?promise-timeout handle>> kill-process*
|
||||
p 1 seconds ?promise-timeout kill-process*
|
||||
s 3 seconds ?promise-timeout 0 =
|
||||
]
|
||||
] unit-test
|
||||
|
@ -181,3 +181,36 @@ io.timeouts io.launcher.unix ;
|
|||
[ wait-for-process ]
|
||||
tri
|
||||
] unit-test
|
||||
|
||||
! Test priority
|
||||
[ 0 ] [
|
||||
<process>
|
||||
{ "bash" "-c" "sleep 2&" } >>command
|
||||
+low-priority+ >>priority
|
||||
run-process status>>
|
||||
] unit-test
|
||||
|
||||
! Check that processes launched with the group option kill their children (or not)
|
||||
! This test should leave two sleeps running for 30 seconds.
|
||||
[
|
||||
<process> { "bash" "-c" "sleep 30& sleep 30" } >>command
|
||||
+same-group+ >>group
|
||||
500 milliseconds >>timeout
|
||||
run-process
|
||||
] [ process-was-killed? ] must-fail-with
|
||||
|
||||
! This test should kill the sleep after 500ms.
|
||||
[
|
||||
<process> { "bash" "-c" "sleep 30& sleep 30" } >>command
|
||||
+new-group+ >>group
|
||||
500 milliseconds >>timeout
|
||||
run-process
|
||||
] [ process-was-killed? ] must-fail-with
|
||||
|
||||
! This test should kill the sleep after 500ms.
|
||||
[
|
||||
<process> { "bash" "-c" "sleep 30& sleep 30" } >>command
|
||||
+new-session+ >>group
|
||||
500 milliseconds >>timeout
|
||||
run-process
|
||||
] [ process-was-killed? ] must-fail-with
|
||||
|
|
|
@ -14,16 +14,23 @@ IN: io.launcher.unix
|
|||
: assoc>env ( assoc -- env )
|
||||
[ "=" glue ] { } assoc>map ;
|
||||
|
||||
: setup-process-group ( process -- process )
|
||||
dup group>> {
|
||||
{ +same-group+ [ ] }
|
||||
{ +new-group+ [ 0 0 setpgid io-error ] }
|
||||
{ +new-session+ [ setsid io-error ] }
|
||||
} case ;
|
||||
|
||||
: setup-priority ( process -- process )
|
||||
dup priority>> [
|
||||
H{
|
||||
{ +lowest-priority+ 20 }
|
||||
{ +low-priority+ 10 }
|
||||
{ +normal-priority+ 0 }
|
||||
{ +high-priority+ -10 }
|
||||
{ +highest-priority+ -20 }
|
||||
{ +realtime-priority+ -20 }
|
||||
} at set-priority
|
||||
{
|
||||
{ +lowest-priority+ [ 20 ] }
|
||||
{ +low-priority+ [ 10 ] }
|
||||
{ +normal-priority+ [ 0 ] }
|
||||
{ +high-priority+ [ -10 ] }
|
||||
{ +highest-priority+ [ -20 ] }
|
||||
{ +realtime-priority+ [ -20 ] }
|
||||
} case set-priority
|
||||
] when* ;
|
||||
|
||||
: reset-fd ( fd -- )
|
||||
|
@ -69,6 +76,7 @@ IN: io.launcher.unix
|
|||
] when ;
|
||||
|
||||
: spawn-process ( process -- * )
|
||||
[ setup-process-group ] [ 2drop 249 _exit ] recover
|
||||
[ setup-priority ] [ 2drop 250 _exit ] recover
|
||||
[ setup-redirection ] [ 2drop 251 _exit ] recover
|
||||
[ current-directory get absolute-path cd ] [ 2drop 252 _exit ] recover
|
||||
|
@ -82,8 +90,12 @@ M: unix current-process-handle ( -- handle ) getpid ;
|
|||
M: unix run-process* ( process -- pid )
|
||||
[ spawn-process ] curry [ ] with-fork ;
|
||||
|
||||
M: unix kill-process* ( pid -- )
|
||||
SIGTERM kill io-error ;
|
||||
M: unix kill-process* ( process -- )
|
||||
[ handle>> SIGTERM ] [ group>> ] bi {
|
||||
{ +same-group+ [ kill ] }
|
||||
{ +new-group+ [ killpg ] }
|
||||
{ +new-session+ [ killpg ] }
|
||||
} case io-error ;
|
||||
|
||||
: find-process ( handle -- process )
|
||||
processes get swap [ nip swap handle>> = ] curry
|
||||
|
|
|
@ -143,8 +143,8 @@ M: launch-error error.
|
|||
"Launch descriptor:" print nl
|
||||
process>> . ;
|
||||
|
||||
M: windows kill-process* ( handle -- )
|
||||
hProcess>> 255 TerminateProcess win32-error=0/f ;
|
||||
M: windows kill-process* ( process -- )
|
||||
handle>> hProcess>> 255 TerminateProcess win32-error=0/f ;
|
||||
|
||||
: dispose-process ( process-information -- )
|
||||
#! From MSDN: "Handles in PROCESS_INFORMATION must be closed
|
||||
|
|
|
@ -80,6 +80,8 @@ FUNCTION: int getaddrinfo ( c-string hostname, c-string servname, addrinfo* hint
|
|||
FUNCTION: c-string getcwd ( c-string buf, size_t size ) ;
|
||||
FUNCTION: pid_t getpid ;
|
||||
FUNCTION: int getdtablesize ;
|
||||
FUNCTION: pid_t getpgrp ;
|
||||
FUNCTION: pid_t getpgid ( pid_t pid ) ;
|
||||
FUNCTION: gid_t getegid ;
|
||||
FUNCTION: uid_t geteuid ;
|
||||
FUNCTION: gid_t getgid ;
|
||||
|
@ -88,6 +90,7 @@ FUNCTION: c-string getenv ( c-string name ) ;
|
|||
FUNCTION: int getgrgid_r ( gid_t gid, group* grp, c-string buffer, size_t bufsize, group** result ) ;
|
||||
FUNCTION: int getgrnam_r ( c-string name, group* grp, c-string buffer, size_t bufsize, group** result ) ;
|
||||
FUNCTION: passwd* getpwent ( ) ;
|
||||
FUNCTION: int killpg ( pid_t pgrp, int sig ) ;
|
||||
FUNCTION: void setpwent ( ) ;
|
||||
FUNCTION: void setpassent ( int stayopen ) ;
|
||||
FUNCTION: passwd* getpwuid ( uid_t uid ) ;
|
||||
|
@ -153,8 +156,10 @@ FUNCTION: int setegid ( gid_t egid ) ;
|
|||
FUNCTION: int seteuid ( uid_t euid ) ;
|
||||
FUNCTION: int setgid ( gid_t gid ) ;
|
||||
FUNCTION: int setgroups ( int ngroups, gid_t* gidset ) ;
|
||||
FUNCTION: int setpgid ( pid_t pid, pid_t gid ) ;
|
||||
FUNCTION: int setregid ( gid_t rgid, gid_t egid ) ;
|
||||
FUNCTION: int setreuid ( uid_t ruid, uid_t euid ) ;
|
||||
FUNCTION: pid_t setsid ( ) ;
|
||||
FUNCTION: int setsockopt ( int s, int level, int optname, void* optval, socklen_t optlen ) ;
|
||||
FUNCTION: int setuid ( uid_t uid ) ;
|
||||
FUNCTION: int socket ( int domain, int type, int protocol ) ;
|
||||
|
|
Loading…
Reference in New Issue