44 createSignal ,
55 Err ,
66 Ok ,
7+ resource ,
78 type Result ,
89 spawn ,
910 withResolvers ,
@@ -16,78 +17,107 @@ import { ExecError } from "./error.ts";
1617
1718type ProcessResultValue = [ number ?, string ?] ;
1819
19- export const createPosixProcess : CreateOSProcess = function * createPosixProcess (
20+ export const createPosixProcess : CreateOSProcess = (
2021 command ,
2122 options ,
22- ) {
23- let processResult = withResolvers < Result < ProcessResultValue > > ( ) ;
23+ ) => {
24+ return resource ( function * ( provide ) {
25+ let processResult = withResolvers < Result < ProcessResultValue > > ( ) ;
2426
25- // Killing all child processes started by this command is surprisingly
26- // tricky. If a process spawns another processes and we kill the parent,
27- // then the child process is NOT automatically killed. Instead we're using
28- // the `detached` option to force the child into its own process group,
29- // which all of its children in turn will inherit. By sending the signal to
30- // `-pid` rather than `pid`, we are sending it to the entire process group
31- // instead. This will send the signal to all processes started by the child
32- // process.
33- //
34- // More information here: https://unix.stackexchange.com/questions/14815/process-descendants
35- let childProcess = spawnProcess ( command , options . arguments || [ ] , {
36- detached : true ,
37- shell : options . shell ,
38- env : options . env ,
39- cwd : options . cwd ,
40- stdio : "pipe" ,
41- } ) ;
27+ // Killing all child processes started by this command is surprisingly
28+ // tricky. If a process spawns another processes and we kill the parent,
29+ // then the child process is NOT automatically killed. Instead we're using
30+ // the `detached` option to force the child into its own process group,
31+ // which all of its children in turn will inherit. By sending the signal to
32+ // `-pid` rather than `pid`, we are sending it to the entire process group
33+ // instead. This will send the signal to all processes started by the child
34+ // process.
35+ //
36+ // More information here: https://unix.stackexchange.com/questions/14815/process-descendants
37+ let childProcess = spawnProcess ( command , options . arguments || [ ] , {
38+ detached : true ,
39+ shell : options . shell ,
40+ env : options . env ,
41+ cwd : options . cwd ,
42+ stdio : "pipe" ,
43+ } ) ;
4244
43- let { pid } = childProcess ;
45+ let { pid } = childProcess ;
4446
45- let io = {
46- stdout : yield * useReadable ( childProcess . stdout ) ,
47- stderr : yield * useReadable ( childProcess . stderr ) ,
48- stdoutDone : withResolvers < void > ( ) ,
49- stderrDone : withResolvers < void > ( ) ,
50- } ;
47+ let io = {
48+ stdout : yield * useReadable ( childProcess . stdout ) ,
49+ stderr : yield * useReadable ( childProcess . stderr ) ,
50+ stdoutDone : withResolvers < void > ( ) ,
51+ stderrDone : withResolvers < void > ( ) ,
52+ } ;
5153
52- let stdout = createSignal < Uint8Array , void > ( ) ;
53- let stderr = createSignal < Uint8Array , void > ( ) ;
54+ let stdout = createSignal < Uint8Array , void > ( ) ;
55+ let stderr = createSignal < Uint8Array , void > ( ) ;
5456
55- yield * spawn ( function * ( ) {
56- let next = yield * io . stdout . next ( ) ;
57- while ( ! next . done ) {
58- stdout . send ( next . value ) ;
59- next = yield * io . stdout . next ( ) ;
60- }
61- stdout . close ( ) ;
62- io . stdoutDone . resolve ( ) ;
63- } ) ;
57+ yield * spawn ( function * ( ) {
58+ let next = yield * io . stdout . next ( ) ;
59+ while ( ! next . done ) {
60+ stdout . send ( next . value ) ;
61+ next = yield * io . stdout . next ( ) ;
62+ }
63+ stdout . close ( ) ;
64+ io . stdoutDone . resolve ( ) ;
65+ } ) ;
6466
65- yield * spawn ( function * ( ) {
66- let next = yield * io . stderr . next ( ) ;
67- while ( ! next . done ) {
68- stderr . send ( next . value ) ;
69- next = yield * io . stderr . next ( ) ;
70- }
71- stderr . close ( ) ;
72- io . stderrDone . resolve ( ) ;
73- } ) ;
67+ yield * spawn ( function * ( ) {
68+ let next = yield * io . stderr . next ( ) ;
69+ while ( ! next . done ) {
70+ stderr . send ( next . value ) ;
71+ next = yield * io . stderr . next ( ) ;
72+ }
73+ stderr . close ( ) ;
74+ io . stderrDone . resolve ( ) ;
75+ } ) ;
7476
75- yield * spawn ( function * trapError ( ) {
76- let [ error ] = yield * once < [ Error ] > ( childProcess , "error" ) ;
77- processResult . resolve ( Err ( error ) ) ;
78- } ) ;
77+ let stdin : Writable < string > = {
78+ send ( data : string ) {
79+ childProcess . stdin . write ( data ) ;
80+ } ,
81+ } ;
7982
80- let stdin : Writable < string > = {
81- send ( data : string ) {
82- childProcess . stdin . write ( data ) ;
83- } ,
84- } ;
83+ yield * spawn ( function * trapError ( ) {
84+ let [ error ] = yield * once < [ Error ] > ( childProcess , "error" ) ;
85+ processResult . resolve ( Err ( error ) ) ;
86+ } ) ;
8587
86- yield * spawn ( function * ( ) {
87- try {
88+ yield * spawn ( function * ( ) {
8889 let value = yield * once < ProcessResultValue > ( childProcess , "close" ) ;
89- // yield* all([io.stdoutDone.operation, io.stderrDone.operation]);
9090 processResult . resolve ( Ok ( value ) ) ;
91+ } ) ;
92+
93+ function * join ( ) {
94+ let result = yield * processResult . operation ;
95+ if ( result . ok ) {
96+ let [ code , signal ] = result . value ;
97+ return { command, options, code, signal } as ExitStatus ;
98+ } else {
99+ throw result . error ;
100+ }
101+ }
102+
103+ function * expect ( ) {
104+ let status : ExitStatus = yield * join ( ) ;
105+ if ( status . code != 0 ) {
106+ throw new ExecError ( status , command , options ) ;
107+ } else {
108+ return status ;
109+ }
110+ }
111+
112+ try {
113+ yield * provide ( {
114+ pid : pid as number ,
115+ stdin,
116+ stdout,
117+ stderr,
118+ join,
119+ expect,
120+ } ) ;
91121 } finally {
92122 try {
93123 if ( typeof childProcess . pid === "undefined" ) {
@@ -101,33 +131,4 @@ export const createPosixProcess: CreateOSProcess = function* createPosixProcess(
101131 }
102132 }
103133 } ) ;
104-
105- function * join ( ) {
106- let result = yield * processResult . operation ;
107- if ( result . ok ) {
108- let [ code , signal ] = result . value ;
109- return { command, options, code, signal } as ExitStatus ;
110- } else {
111- throw result . error ;
112- }
113- }
114-
115- function * expect ( ) {
116- let status : ExitStatus = yield * join ( ) ;
117- if ( status . code != 0 ) {
118- throw new ExecError ( status , command , options ) ;
119- } else {
120- return status ;
121- }
122- }
123-
124- // FYI: this function starts a process and returns without blocking
125- return {
126- pid : pid as number ,
127- stdin,
128- stdout,
129- stderr,
130- join,
131- expect,
132- } ;
133134} ;
0 commit comments