77
77
import com .oracle .graal .python .runtime .PythonOptions ;
78
78
import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
79
79
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
80
+ import com .oracle .truffle .api .TruffleFile ;
81
+ import com .oracle .truffle .api .TruffleLanguage .Env ;
80
82
import com .oracle .truffle .api .TruffleLogger ;
81
83
import com .oracle .truffle .api .dsl .Cached ;
82
84
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
@@ -141,14 +143,11 @@ private synchronized int forkExec(PList args, PList execList, @SuppressWarnings(
141
143
}
142
144
143
145
File cwdFile ;
144
- try {
145
- if (getContext ().getEnv ().getPublicTruffleFile (cwd ).exists ()) {
146
- cwdFile = new File (cwd );
147
- } else {
148
- throw raise (PythonBuiltinClassType .OSError , ErrorMessages .WORK_DIR_NOT_ACCESSIBLE , cwd );
149
- }
150
- } catch (SecurityException e ) {
151
- throw raise (PythonBuiltinClassType .OSError , e );
146
+ Env truffleEnv = context .getEnv ();
147
+ if (getSafeTruffleFile (truffleEnv , cwd ).exists ()) {
148
+ cwdFile = new File (cwd );
149
+ } else {
150
+ throw raise (PythonBuiltinClassType .OSError , ErrorMessages .WORK_DIR_NOT_ACCESSIBLE , cwd );
152
151
}
153
152
154
153
SequenceStorage envStorage = env .getSequenceStorage ();
@@ -209,18 +208,22 @@ private synchronized int forkExec(PList args, PList execList, @SuppressWarnings(
209
208
} else {
210
209
argStrings .set (0 , path );
211
210
}
212
- try {
213
- return exec (argStrings , cwdFile , envMap , p2cwrite , p2cread , c2pwrite , c2pread , errwrite , errpipe_write , resources , errread );
214
- } catch (IOException ex ) {
215
- if (firstError == null ) {
216
- firstError = ex ;
211
+ TruffleFile executableFile = getSafeTruffleFile (truffleEnv , argStrings .get (0 ));
212
+ if (executableFile .isExecutable ()) {
213
+ try {
214
+ return exec (argStrings , cwdFile , envMap , p2cwrite , p2cread , c2pwrite , c2pread , errwrite , errpipe_write , resources , errread );
215
+ } catch (IOException ex ) {
216
+ if (firstError == null ) {
217
+ firstError = ex ;
218
+ }
217
219
}
220
+ } else {
221
+ LOGGER .finest (() -> "_posixsubprocess.fork_exec not executable: " + executableFile );
218
222
}
219
223
for (int j = 1 ; j < executableListLen ; j ++) {
220
224
argStrings .remove (1 );
221
225
}
222
226
}
223
- assert firstError != null ;
224
227
if (errpipe_write != -1 ) {
225
228
handleIOError (errpipe_write , resources , firstError );
226
229
}
@@ -285,6 +288,14 @@ private int exec(ArrayList<String> argStrings, File cwd, Map<String, String> env
285
288
return resources .registerChild (process );
286
289
}
287
290
291
+ private TruffleFile getSafeTruffleFile (Env env , String path ) {
292
+ try {
293
+ return env .getPublicTruffleFile (path );
294
+ } catch (SecurityException e ) {
295
+ throw raise (PythonBuiltinClassType .OSError , e );
296
+ }
297
+ }
298
+
288
299
private String checkNullBytesAndEncode (PythonObjectLibrary pyLib , PBytes bytesObj ) {
289
300
byte [] bytes ;
290
301
try {
@@ -307,12 +318,18 @@ private String checkNullBytesAndEncode(PythonObjectLibrary pyLib, PBytes bytesOb
307
318
@ TruffleBoundary (allowInlining = true )
308
319
private void handleIOError (int errpipe_write , PosixResources resources , IOException e ) {
309
320
// write exec error information here. Data format: "exception name:hex
310
- // errno:description"
321
+ // errno:description". The exception can be null if we did not find any file in the
322
+ // execList that could be executed
311
323
Channel err = resources .getFileChannel (errpipe_write );
312
324
if (!(err instanceof WritableByteChannel )) {
313
325
throw raise (PythonBuiltinClassType .OSError , ErrorMessages .ERROR_WRITING_FORKEXEC );
314
326
} else {
315
- ErrorAndMessagePair pair = OSErrorEnum .fromException (e );
327
+ ErrorAndMessagePair pair ;
328
+ if (e == null ) {
329
+ pair = new ErrorAndMessagePair (OSErrorEnum .ENOENT , OSErrorEnum .ENOENT .getMessage ());
330
+ } else {
331
+ pair = OSErrorEnum .fromException (e );
332
+ }
316
333
try {
317
334
((WritableByteChannel ) err ).write (ByteBuffer .wrap (("OSError:" + Long .toHexString (pair .oserror .getNumber ()) + ":" + pair .message ).getBytes ()));
318
335
} catch (IOException e1 ) {
0 commit comments