@@ -202,7 +202,7 @@ public PosixResources() {
202
202
inodes = new HashMap <>();
203
203
}
204
204
205
- @ TruffleBoundary ( allowInlining = true )
205
+ @ TruffleBoundary
206
206
public void setEnv (Env env ) {
207
207
synchronized (files ) {
208
208
files .get (FD_STDIN ).setNewChannel (env .in ());
@@ -241,18 +241,19 @@ private void removeFD(int fd) throws IOException {
241
241
}
242
242
}
243
243
244
+ /**
245
+ * ATTENTION: This method must be used in a synchronized block (sync on {@link #files}) until.
246
+ */
244
247
@ TruffleBoundary
245
248
private void dupFD (int fd1 , int fd2 ) {
246
249
ChannelWrapper channelWrapper = files .getOrDefault (fd1 , null );
247
250
if (channelWrapper != null ) {
248
- synchronized (files ) {
249
- channelWrapper .cnt += 1 ;
250
- files .put (fd2 , channelWrapper );
251
- }
251
+ channelWrapper .cnt += 1 ;
252
+ files .put (fd2 , channelWrapper );
252
253
}
253
254
}
254
255
255
- @ TruffleBoundary ( allowInlining = true )
256
+ @ TruffleBoundary
256
257
public Channel getFileChannel (int fd , ValueProfile classProfile ) {
257
258
ChannelWrapper channelWrapper = files .getOrDefault (fd , null );
258
259
if (channelWrapper != null ) {
@@ -261,7 +262,7 @@ public Channel getFileChannel(int fd, ValueProfile classProfile) {
261
262
return null ;
262
263
}
263
264
264
- @ TruffleBoundary ( allowInlining = true )
265
+ @ TruffleBoundary
265
266
public FileLock getFileLock (int fd ) {
266
267
ChannelWrapper channelWrapper = files .getOrDefault (fd , null );
267
268
if (channelWrapper != null ) {
@@ -270,15 +271,15 @@ public FileLock getFileLock(int fd) {
270
271
return null ;
271
272
}
272
273
273
- @ TruffleBoundary ( allowInlining = true )
274
+ @ TruffleBoundary
274
275
public void setFileLock (int fd , FileLock lock ) {
275
276
ChannelWrapper channelWrapper = files .getOrDefault (fd , null );
276
277
if (channelWrapper != null ) {
277
278
channelWrapper .lock = lock ;
278
279
}
279
280
}
280
281
281
- @ TruffleBoundary ( allowInlining = true )
282
+ @ TruffleBoundary
282
283
public Channel getFileChannel (int fd ) {
283
284
ChannelWrapper channelWrapper = files .getOrDefault (fd , null );
284
285
if (channelWrapper != null ) {
@@ -301,7 +302,7 @@ public PSocket getSocket(int fd) {
301
302
return null ;
302
303
}
303
304
304
- @ TruffleBoundary ( allowInlining = true )
305
+ @ TruffleBoundary
305
306
public void close (int fd ) {
306
307
try {
307
308
removeFD (fd );
@@ -311,17 +312,19 @@ public void close(int fd) {
311
312
312
313
@ TruffleBoundary
313
314
public int openSocket (PSocket socket ) {
314
- int fd = nextFreeFd ();
315
- addFD (fd , socket );
316
- return fd ;
315
+ synchronized (files ) {
316
+ int fd = nextFreeFd ();
317
+ addFD (fd , socket );
318
+ return fd ;
319
+ }
317
320
}
318
321
319
322
@ TruffleBoundary
320
323
public void reopenSocket (PSocket socket , int fd ) {
321
324
addFD (fd , socket );
322
325
}
323
326
324
- @ TruffleBoundary ( allowInlining = true )
327
+ @ TruffleBoundary
325
328
public void fdopen (int fd , Channel fc ) {
326
329
files .get (fd ).channel = fc ;
327
330
}
@@ -333,78 +336,89 @@ public void fdopen(int fd, Channel fc) {
333
336
* @param fc the newly created Channel
334
337
* @return the file descriptor associated with the new Channel
335
338
*/
336
- @ TruffleBoundary ( allowInlining = true )
339
+ @ TruffleBoundary
337
340
public int open (TruffleFile path , Channel fc ) {
338
- int fd = nextFreeFd ();
339
- addFD (fd , fc , path .getAbsoluteFile ().getPath ());
340
- return fd ;
341
+ synchronized (files ) {
342
+ int fd = nextFreeFd ();
343
+ addFD (fd , fc , path .getAbsoluteFile ().getPath ());
344
+ return fd ;
345
+ }
341
346
}
342
347
343
- @ TruffleBoundary ( allowInlining = true )
348
+ @ TruffleBoundary
344
349
public int dup (int fd ) {
345
- int dupFd = nextFreeFd ();
346
- dupFD (fd , dupFd );
347
- return dupFd ;
350
+ synchronized (files ) {
351
+ int dupFd = nextFreeFd ();
352
+ dupFD (fd , dupFd );
353
+ return dupFd ;
354
+ }
348
355
}
349
356
350
- @ TruffleBoundary ( allowInlining = true )
357
+ @ TruffleBoundary
351
358
public int dup2 (int fd , int fd2 ) throws IOException {
352
- removeFD (fd2 );
353
- dupFD (fd , fd2 );
354
- return fd2 ;
359
+ synchronized (files ) {
360
+ removeFD (fd2 );
361
+ dupFD (fd , fd2 );
362
+ return fd2 ;
363
+ }
355
364
}
356
365
357
- @ TruffleBoundary ( allowInlining = true )
366
+ @ TruffleBoundary
358
367
public boolean fsync (int fd ) {
359
368
return files .getOrDefault (fd , null ) != null ;
360
369
}
361
370
362
- @ TruffleBoundary ( allowInlining = true )
371
+ @ TruffleBoundary
363
372
public void ftruncate (int fd , long size ) throws IOException {
364
373
Channel channel = getFileChannel (fd );
365
374
if (channel instanceof SeekableByteChannel ) {
366
375
((SeekableByteChannel ) channel ).truncate (size );
367
376
}
368
377
}
369
378
370
- @ TruffleBoundary ( allowInlining = true )
379
+ @ TruffleBoundary
371
380
public int [] pipe () throws IOException {
372
- Pipe pipe = Pipe .open ();
373
- int readFD = nextFreeFd ();
374
- addFD (readFD , pipe .source ());
381
+ synchronized (files ) {
382
+ Pipe pipe = Pipe .open ();
383
+ int readFD = nextFreeFd ();
384
+ addFD (readFD , pipe .source ());
375
385
376
- int writeFD = nextFreeFd ();
377
- addFD (writeFD , pipe .sink ());
386
+ int writeFD = nextFreeFd ();
387
+ addFD (writeFD , pipe .sink ());
378
388
379
- return new int []{readFD , writeFD };
389
+ return new int []{readFD , writeFD };
390
+ }
380
391
}
381
392
382
- @ TruffleBoundary (allowInlining = true )
393
+ /**
394
+ * ATTENTION: This method must be used in a synchronized block (sync on {@link #files}) until
395
+ * the gained file descriptors are written to the map. Otherwise, concurrent threads may get the
396
+ * same FDs.
397
+ */
398
+ @ TruffleBoundary
383
399
private int nextFreeFd () {
384
- synchronized (files ) {
385
- int fd1 = files .firstKey ();
386
- for (int fd2 : files .keySet ()) {
387
- if (fd2 == fd1 ) {
388
- continue ;
389
- }
390
- if (fd2 - fd1 > 1 ) {
391
- return fd1 + 1 ;
392
- } else {
393
- fd1 = fd2 ;
394
- }
400
+ int fd1 = files .firstKey ();
401
+ for (int fd2 : files .keySet ()) {
402
+ if (fd2 == fd1 ) {
403
+ continue ;
404
+ }
405
+ if (fd2 - fd1 > 1 ) {
406
+ return fd1 + 1 ;
407
+ } else {
408
+ fd1 = fd2 ;
395
409
}
396
- return files .lastKey () + 1 ;
397
410
}
411
+ return files .lastKey () + 1 ;
398
412
}
399
413
400
- @ TruffleBoundary ( allowInlining = true )
414
+ @ TruffleBoundary
401
415
public int registerChild (Process child ) {
402
416
int pid = nextFreePid ();
403
417
children .set (pid , child );
404
418
return pid ;
405
419
}
406
420
407
- @ TruffleBoundary ( allowInlining = true )
421
+ @ TruffleBoundary
408
422
private int nextFreePid () {
409
423
synchronized (children ) {
410
424
for (int i = 0 ; i < children .size (); i ++) {
0 commit comments