@@ -31,7 +31,15 @@ class Job {
31
31
#active_timeouts;
32
32
#active_parent_processes;
33
33
34
- constructor ( { runtime, files, args, stdin, timeouts, memory_limits } ) {
34
+ constructor ( {
35
+ runtime,
36
+ files,
37
+ args,
38
+ stdin,
39
+ timeouts,
40
+ memory_limits,
41
+ packages,
42
+ } ) {
35
43
this . uuid = uuidv4 ( ) ;
36
44
37
45
this . logger = logplease . create ( `job/${ this . uuid } ` ) ;
@@ -52,6 +60,8 @@ class Job {
52
60
this . stdin += '\n' ;
53
61
}
54
62
63
+ this . packages = packages ;
64
+
55
65
this . #active_timeouts = [ ] ;
56
66
this . #active_parent_processes = [ ] ;
57
67
@@ -141,9 +151,12 @@ class Job {
141
151
this . logger . debug ( `Finished exit cleanup` ) ;
142
152
}
143
153
144
- async safe_call ( file , args , timeout , memory_limit , eventBus = null ) {
154
+ async safe_call ( file , args , timeout , memory_limit , options ) {
145
155
return new Promise ( ( resolve , reject ) => {
146
- const nonetwork = config . disable_networking ? [ 'nosocket' ] : [ ] ;
156
+ const nonetwork =
157
+ config . disable_networking && ! options . elevated_permissions
158
+ ? [ 'nosocket' ]
159
+ : [ ] ;
147
160
148
161
const prlimit = [
149
162
'prlimit' ,
@@ -169,26 +182,33 @@ class Job {
169
182
var stderr = '' ;
170
183
var output = '' ;
171
184
185
+ const proc_info = { } ;
186
+ if ( ! options . elevated_permissions ) {
187
+ proc_info . uid = this . uid ;
188
+ proc_info . gid = this . gid ;
189
+ }
190
+ if ( options . env ) {
191
+ proc_info . env = options . env ;
192
+ }
172
193
const proc = cp . spawn ( proc_call [ 0 ] , proc_call . splice ( 1 ) , {
173
194
stdio : 'pipe' ,
174
195
cwd : this . dir ,
175
- uid : this . uid ,
176
- gid : this . gid ,
177
196
detached : true , //give this process its own process group
197
+ ...proc_info ,
178
198
} ) ;
179
199
180
200
this . #active_parent_processes. push ( proc ) ;
181
201
182
- if ( eventBus === null ) {
202
+ if ( ! options . eventBus ) {
183
203
proc . stdin . write ( this . stdin ) ;
184
204
proc . stdin . end ( ) ;
185
205
proc . stdin . destroy ( ) ;
186
206
} else {
187
- eventBus . on ( 'stdin' , data => {
207
+ options . eventBus . on ( 'stdin' , data => {
188
208
proc . stdin . write ( data ) ;
189
209
} ) ;
190
210
191
- eventBus . on ( 'kill' , signal => {
211
+ options . eventBus . on ( 'kill' , signal => {
192
212
proc . kill ( signal ) ;
193
213
} ) ;
194
214
}
@@ -203,8 +223,8 @@ class Job {
203
223
this . #active_timeouts. push ( kill_timeout ) ;
204
224
205
225
proc . stderr . on ( 'data' , async data => {
206
- if ( eventBus !== null ) {
207
- eventBus . emit ( 'stderr' , data ) ;
226
+ if ( options . eventBus ) {
227
+ options . eventBus . emit ( 'stderr' , data ) ;
208
228
} else if ( stderr . length > this . runtime . output_max_size ) {
209
229
this . logger . info ( `stderr length exceeded` ) ;
210
230
process . kill ( proc . pid , 'SIGKILL' ) ;
@@ -215,8 +235,8 @@ class Job {
215
235
} ) ;
216
236
217
237
proc . stdout . on ( 'data' , async data => {
218
- if ( eventBus !== null ) {
219
- eventBus . emit ( 'stdout' , data ) ;
238
+ if ( options . eventBus ) {
239
+ options . eventBus . emit ( 'stdout' , data ) ;
220
240
} else if ( stdout . length > this . runtime . output_max_size ) {
221
241
this . logger . info ( `stdout length exceeded` ) ;
222
242
process . kill ( proc . pid , 'SIGKILL' ) ;
@@ -241,6 +261,7 @@ class Job {
241
261
}
242
262
243
263
async execute ( ) {
264
+ // TODO: group with execute_interactively
244
265
if ( this . state !== job_states . PRIMED ) {
245
266
throw new Error (
246
267
'Job must be in primed state, current state: ' +
@@ -250,6 +271,29 @@ class Job {
250
271
251
272
this . logger . info ( `Executing job runtime=${ this . runtime . toString ( ) } ` ) ;
252
273
274
+ let install ;
275
+
276
+ // TODO: install timeouts, install memory limits, install errored
277
+ if ( this . runtime . package_support && this . packages . length > 0 ) {
278
+ install = await this . safe_call (
279
+ this . runtime . installPackages ,
280
+ this . packages . map (
281
+ p => `${ this . runtime . flake_path } .packages.${ p } `
282
+ ) ,
283
+ - 1 ,
284
+ - 1 ,
285
+ {
286
+ elevated_permissions : true ,
287
+ }
288
+ ) ;
289
+ }
290
+
291
+ const env = { } ;
292
+ if ( install && install . stdout !== '' && install . code === 0 ) {
293
+ const install_json = JSON . parse ( install . stdout ) ;
294
+ env . PISTON_PACKAGES_PATH = install_json . map ( i => i . outputs . out ) . join ( ':' ) ;
295
+ }
296
+
253
297
const code_files = this . files . filter ( file => file . encoding == 'utf8' ) ;
254
298
255
299
this . logger . debug ( 'Compiling' ) ;
@@ -262,7 +306,8 @@ class Job {
262
306
this . runtime . compile ,
263
307
code_files . map ( x => x . name ) ,
264
308
this . timeouts . compile ,
265
- this . memory_limits . compile
309
+ this . memory_limits . compile ,
310
+ { env }
266
311
) ;
267
312
compile_errored = compile . code !== 0 ;
268
313
}
@@ -275,13 +320,15 @@ class Job {
275
320
this . runtime . run ,
276
321
[ code_files [ 0 ] . name , ...this . args ] ,
277
322
this . timeouts . run ,
278
- this . memory_limits . run
323
+ this . memory_limits . run ,
324
+ { env }
279
325
) ;
280
326
}
281
327
282
328
this . state = job_states . EXECUTED ;
283
329
284
330
return {
331
+ install,
285
332
compile,
286
333
run,
287
334
language : this . runtime . language ,
@@ -311,7 +358,7 @@ class Job {
311
358
code_files . map ( x => x . name ) ,
312
359
this . timeouts . compile ,
313
360
this . memory_limits . compile ,
314
- eventBus
361
+ { eventBus }
315
362
) ;
316
363
317
364
eventBus . emit ( 'exit' , 'compile' , { error, code, signal } ) ;
@@ -326,7 +373,7 @@ class Job {
326
373
[ code_files [ 0 ] . name , ...this . args ] ,
327
374
this . timeouts . run ,
328
375
this . memory_limits . run ,
329
- eventBus
376
+ { eventBus }
330
377
) ;
331
378
332
379
eventBus . emit ( 'exit' , 'run' , { error, code, signal } ) ;
0 commit comments