127
127
import com .oracle .truffle .api .source .Source ;
128
128
import com .oracle .truffle .api .utilities .CyclicAssumption ;
129
129
import com .oracle .truffle .llvm .api .Toolchain ;
130
- import java .util .Iterator ;
131
- import java .util .Set ;
132
130
import java .util .SortedMap ;
133
131
import java .util .TreeMap ;
134
132
import java .util .concurrent .CountDownLatch ;
@@ -472,8 +470,6 @@ public Thread getOwner() {
472
470
private final ChildContextData childContextData ;
473
471
private final SharedContextData sharedContextData ;
474
472
475
- private final Set <Integer > fdsToClose = new HashSet <>();
476
-
477
473
public static final class ChildContextData {
478
474
private int exitCode = 0 ;
479
475
private boolean signaled ;
@@ -525,44 +521,53 @@ public boolean compareAndSetExiting(boolean expect, boolean update) {
525
521
526
522
public static final class SharedContextData {
527
523
528
- private int counter = 0 ;
524
+ private int fdCounter = 0 ;
529
525
530
- private final SortedMap <Integer , LinkedBlockingQueue <Object >> fdData = new TreeMap <>();
531
- private final Map <Integer , Integer > fdsToKeep = new HashMap <>();
526
+ /**
527
+ * Maps the two fake file descriptors created in {@link #pipe()} to one
528
+ * {@link LinkedBlockingQueue}
529
+ */
530
+ private final SortedMap <Integer , LinkedBlockingQueue <Object >> pipeData = new TreeMap <>();
532
531
533
- @ TruffleBoundary
534
- public boolean isFdToKeep (int fd ) {
535
- synchronized (fdsToKeep ) {
536
- return fdsToKeep .containsKey (fd );
537
- }
538
- }
532
+ /**
533
+ * Holds ref count of file descriptors which were passed over to a spawned child context.
534
+ * This can be either:<br>
535
+ * <ul>
536
+ * <li>fake file descriptors created via {@link #pipe()}</li>
537
+ * <li>real file descriptors coming from the posix implementation</li>
538
+ * </ul>
539
+ */
540
+ private final Map <Integer , Integer > fdRefCount = new HashMap <>();
539
541
542
+ /**
543
+ * Increases reference count for the given file descriptor.
544
+ */
540
545
@ TruffleBoundary
541
- public void addFdToKeep (int fd ) {
542
- synchronized (fdsToKeep ) {
543
- Integer c = fdsToKeep .get (fd );
544
- if (c == null ) {
545
- c = 1 ;
546
- } else {
547
- c = c + 1 ;
548
- }
549
- fdsToKeep .put (fd , c );
546
+ private void incrementFDRefCount (int fd ) {
547
+ synchronized (fdRefCount ) {
548
+ fdRefCount .compute (fd , (f , count ) -> (count == null ) ? 1 : count + 1 );
550
549
}
551
550
}
552
551
552
+ /**
553
+ * Decreases reference count for the given file descriptor.
554
+ *
555
+ * @return {@code true} if ref count was decreased, {@link false} if ref count isn't tracked
556
+ * anymore.
557
+ */
553
558
@ TruffleBoundary
554
- public boolean removeFdToKeep (int fd ) {
555
- synchronized (fdsToKeep ) {
556
- Integer c = fdsToKeep .get (fd );
559
+ public boolean decrementFDRefCount (int fd ) {
560
+ synchronized (fdRefCount ) {
561
+ Integer c = fdRefCount .get (fd );
557
562
if (c == null ) {
558
563
return false ;
559
564
}
560
- if (c == 1 ) {
561
- fdsToKeep .remove (fd );
562
- return true ;
563
- } else {
564
- fdsToKeep .put (fd , c - 1 );
565
+ if (c == 0 ) {
566
+ fdRefCount .remove (fd );
565
567
return false ;
568
+ } else {
569
+ fdRefCount .put (fd , c - 1 );
570
+ return true ;
566
571
}
567
572
}
568
573
}
@@ -573,21 +578,21 @@ public boolean removeFdToKeep(int fd) {
573
578
*/
574
579
@ TruffleBoundary
575
580
public int [] pipe () {
576
- synchronized (fdData ) {
581
+ synchronized (pipeData ) {
577
582
LinkedBlockingQueue <Object > q = new LinkedBlockingQueue <>();
578
- int readFD = --counter ;
579
- fdData .put (readFD , q );
580
- int writeFD = --counter ;
581
- fdData .put (writeFD , q );
583
+ int readFD = --fdCounter ;
584
+ pipeData .put (readFD , q );
585
+ int writeFD = --fdCounter ;
586
+ pipeData .put (writeFD , q );
582
587
return new int []{readFD , writeFD };
583
588
}
584
589
}
585
590
586
591
@ TruffleBoundary
587
- public boolean addSharedContextData (int fd , byte [] bytes , Runnable noFDHandler , Runnable brokenPipeHandler ) {
592
+ public boolean addPipeData (int fd , byte [] bytes , Runnable noFDHandler , Runnable brokenPipeHandler ) {
588
593
LinkedBlockingQueue <Object > q = null ;
589
- synchronized (fdData ) {
590
- q = fdData .get (fd );
594
+ synchronized (pipeData ) {
595
+ q = pipeData .get (fd );
591
596
if (q == null ) {
592
597
noFDHandler .run ();
593
598
throw CompilerDirectives .shouldNotReachHere ();
@@ -603,17 +608,17 @@ public boolean addSharedContextData(int fd, byte[] bytes, Runnable noFDHandler,
603
608
}
604
609
605
610
@ TruffleBoundary
606
- public void closeFd (int fd ) {
607
- synchronized (fdData ) {
608
- fdData .remove (fd );
611
+ public void closePipe (int fd ) {
612
+ synchronized (pipeData ) {
613
+ pipeData .remove (fd );
609
614
}
610
615
}
611
616
612
617
@ TruffleBoundary
613
- public Object takeSharedContextData (Node node , int fd , Runnable noFDHandler ) {
618
+ public Object takePipeData (Node node , int fd , Runnable noFDHandler ) {
614
619
LinkedBlockingQueue <Object > q ;
615
- synchronized (fdData ) {
616
- q = fdData .get (fd );
620
+ synchronized (pipeData ) {
621
+ q = pipeData .get (fd );
617
622
if (q == null ) {
618
623
noFDHandler .run ();
619
624
throw CompilerDirectives .shouldNotReachHere ();
@@ -635,8 +640,8 @@ public Object takeSharedContextData(Node node, int fd, Runnable noFDHandler) {
635
640
@ TruffleBoundary
636
641
public boolean isBlocking (int fd ) {
637
642
LinkedBlockingQueue <Object > q ;
638
- synchronized (fdData ) {
639
- q = fdData .get (fd );
643
+ synchronized (pipeData ) {
644
+ q = pipeData .get (fd );
640
645
if (q == null ) {
641
646
return false ;
642
647
}
@@ -649,7 +654,7 @@ public boolean isBlocking(int fd) {
649
654
}
650
655
651
656
@ TruffleBoundary
652
- public void closeFDs (List <Integer > fds ) {
657
+ public static void closeFDs (List <Integer > fds ) {
653
658
synchronized (fds ) {
654
659
for (Integer fd : fds ) {
655
660
fds .remove (fd );
@@ -662,7 +667,7 @@ private static int getPairFd(int fd) {
662
667
}
663
668
664
669
private boolean isClosed (int fd ) {
665
- return fdData .get (fd ) == null && fd >= counter ;
670
+ return pipeData .get (fd ) == null && fd >= fdCounter ;
666
671
}
667
672
}
668
673
@@ -671,7 +676,7 @@ public PythonContext(PythonLanguage language, TruffleLanguage.Env env, Python3Co
671
676
this .core = core ;
672
677
this .env = env ;
673
678
this .childContextData = (ChildContextData ) env .getConfig ().get (CHILD_CONTEXT_DATA );
674
- this .sharedContextData = this .childContextData == null ? new SharedContextData () : null ;
679
+ this .sharedContextData = this .childContextData == null ? new SharedContextData () : childContextData . parentCtx . sharedContextData ;
675
680
this .handler = new AsyncHandler (this );
676
681
this .sharedFinalizer = new AsyncHandler .SharedFinalizer (this );
677
682
this .optionValues = PythonOptions .createOptionValuesStorage (env );
@@ -701,8 +706,8 @@ public ChildContextData getChildContextData() {
701
706
return childContextData ;
702
707
}
703
708
704
- public synchronized SharedContextData getSharedContextData () {
705
- return isChildContext () ? childContextData . parentCtx . sharedContextData : this . sharedContextData ;
709
+ public SharedContextData getSharedContextData () {
710
+ return sharedContextData ;
706
711
}
707
712
708
713
public long spawnTruffleContext (int fd , int sentinel , int [] fdsToKeep ) {
@@ -723,19 +728,12 @@ public long spawnTruffleContext(int fd, int sentinel, int[] fdsToKeep) {
723
728
for (int fdToKeep : fdsToKeep ) {
724
729
// prevent file descriptors from being closed when passed to another "process",
725
730
// equivalent to fds_to_keep arg in posix fork_exec
726
- getSharedContextData ().addFdToKeep (fdToKeep );
731
+ getSharedContextData ().incrementFDRefCount (fdToKeep );
727
732
}
728
733
start (thread );
729
734
return tid ;
730
735
}
731
736
732
- @ TruffleBoundary
733
- public void closeLater (int fd ) {
734
- synchronized (fdsToClose ) {
735
- fdsToClose .add (fd );
736
- }
737
- }
738
-
739
737
@ TruffleBoundary
740
738
private static void start (Thread thread ) {
741
739
thread .start ();
@@ -788,7 +786,7 @@ public void run() {
788
786
LOGGER .log (Level .FINE , t , () -> "exception while closing spawned child context" );
789
787
}
790
788
}
791
- data .parentCtx .sharedContextData .closeFd (sentinel );
789
+ data .parentCtx .sharedContextData .closePipe (sentinel );
792
790
}
793
791
} catch (ThreadDeath td ) {
794
792
// as a result of of TruffleContext.closeCancelled()
@@ -1404,29 +1402,9 @@ public void finalizeContext() {
1404
1402
disposeThreadStates ();
1405
1403
}
1406
1404
cleanupHPyResources ();
1407
- if (!cancelling ) {
1408
- synchronized (fdsToClose ) {
1409
- Iterator <Integer > it = fdsToClose .iterator ();
1410
- while (it .hasNext ()) {
1411
- int fd = it .next ();
1412
- if (getSharedContextData ().removeFdToKeep (fd )) {
1413
- it .remove ();
1414
- if (fd > 0 ) {
1415
- try {
1416
- PosixSupportLibrary .getUncached ().close (getPosixSupport (), fd );
1417
- } catch (PosixSupportLibrary .PosixException ex ) {
1418
- LOGGER .log (Level .FINEST , ex , () -> "got PosixException while closing file discriptor " + fd );
1419
- }
1420
- } else {
1421
- getSharedContextData ().closeFd (fd );
1422
- }
1423
- }
1424
- }
1425
- }
1426
- }
1427
1405
for (int fd : getChildContextFDs ()) {
1428
- if (getSharedContextData ().removeFdToKeep (fd )) {
1429
- getSharedContextData ().closeFd (fd );
1406
+ if (! getSharedContextData ().decrementFDRefCount (fd )) {
1407
+ getSharedContextData ().closePipe (fd );
1430
1408
}
1431
1409
}
1432
1410
mainThread = null ;
0 commit comments