30
30
import static com .oracle .graal .python .builtins .PythonOS .getPythonOS ;
31
31
import static com .oracle .graal .python .builtins .modules .SysModuleBuiltins .T_CACHE_TAG ;
32
32
import static com .oracle .graal .python .builtins .modules .SysModuleBuiltins .T__MULTIARCH ;
33
+ import static com .oracle .graal .python .builtins .modules .io .IONodes .T_CLOSED ;
34
+ import static com .oracle .graal .python .builtins .modules .io .IONodes .T_FLUSH ;
33
35
import static com .oracle .graal .python .builtins .objects .str .StringUtils .cat ;
34
36
import static com .oracle .graal .python .builtins .objects .thread .PThread .GRAALPYTHON_THREADS ;
35
37
import static com .oracle .graal .python .nodes .BuiltinNames .T_SHA3 ;
38
+ import static com .oracle .graal .python .nodes .BuiltinNames .T_STDERR ;
39
+ import static com .oracle .graal .python .nodes .BuiltinNames .T_STDOUT ;
36
40
import static com .oracle .graal .python .nodes .BuiltinNames .T_SYS ;
37
41
import static com .oracle .graal .python .nodes .BuiltinNames .T_THREADING ;
38
42
import static com .oracle .graal .python .nodes .BuiltinNames .T___BUILTINS__ ;
145
149
import com .oracle .graal .python .compiler .CodeUnit ;
146
150
import com .oracle .graal .python .lib .PyObjectCallMethodObjArgs ;
147
151
import com .oracle .graal .python .lib .PyObjectGetAttr ;
152
+ import com .oracle .graal .python .lib .PyObjectIsTrueNode ;
148
153
import com .oracle .graal .python .nodes .ErrorMessages ;
149
154
import com .oracle .graal .python .nodes .PRaiseNode ;
150
155
import com .oracle .graal .python .nodes .SpecialAttributeNames ;
151
156
import com .oracle .graal .python .nodes .SpecialMethodNames ;
157
+ import com .oracle .graal .python .nodes .WriteUnraisableNode ;
152
158
import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
153
159
import com .oracle .graal .python .nodes .call .CallNode ;
154
160
import com .oracle .graal .python .nodes .object .SetDictNode ;
@@ -1526,19 +1532,24 @@ public void patch(Env newEnv) {
1526
1532
}
1527
1533
1528
1534
private void importSiteIfForced () {
1529
- if (getOption (PythonOptions .ForceImportSite )) {
1530
- AbstractImportNode .importModule (T_SITE );
1531
- }
1532
- if (!getOption (PythonOptions .WarnOptions ).isEmpty ()) {
1533
- // we must force an import of the warnings module here if warnings were passed
1534
- AbstractImportNode .importModule (T_WARNINGS );
1535
- }
1536
- if (getOption (PythonOptions .InputFilePath ).isEmpty ()) {
1537
- // When InputFilePath is set, this is handled by __graalpython__.run_path
1538
- addSysPath0 ();
1539
- }
1540
- if (getOption (PythonOptions .SetupLLVMLibraryPaths )) {
1541
- ImpModuleBuiltins .importFrozenModuleObject (this , toTruffleStringUncached ("graalpy.sulong_support" ), false );
1535
+ try {
1536
+ if (getOption (PythonOptions .ForceImportSite )) {
1537
+ AbstractImportNode .importModule (T_SITE );
1538
+ }
1539
+ if (!getOption (PythonOptions .WarnOptions ).isEmpty ()) {
1540
+ // we must force an import of the warnings module here if warnings were passed
1541
+ AbstractImportNode .importModule (T_WARNINGS );
1542
+ }
1543
+ if (getOption (PythonOptions .InputFilePath ).isEmpty ()) {
1544
+ // When InputFilePath is set, this is handled by __graalpython__.run_path
1545
+ addSysPath0 ();
1546
+ }
1547
+ if (getOption (PythonOptions .SetupLLVMLibraryPaths )) {
1548
+ ImpModuleBuiltins .importFrozenModuleObject (this , toTruffleStringUncached ("graalpy.sulong_support" ), false );
1549
+ }
1550
+ } catch (PException e ) {
1551
+ flushStdFiles ();
1552
+ throw e ;
1542
1553
}
1543
1554
}
1544
1555
@@ -2013,6 +2024,7 @@ public void finalizeContext() {
2013
2024
finalizing = true ;
2014
2025
// interrupt and join or kill python threads
2015
2026
joinThreads ();
2027
+ flushStdFiles ();
2016
2028
if (cApiContext != null ) {
2017
2029
cApiContext .finalizeCApi ();
2018
2030
}
@@ -2029,6 +2041,34 @@ public void finalizeContext() {
2029
2041
mainThread = null ;
2030
2042
}
2031
2043
2044
+ // Equivalent of CPython's flush_std_files
2045
+ @ TruffleBoundary
2046
+ public void flushStdFiles () {
2047
+ PythonModule sysModule = getSysModule ();
2048
+ flushFile (sysModule .getAttribute (T_STDOUT ), true );
2049
+ flushFile (sysModule .getAttribute (T_STDERR ), false );
2050
+ }
2051
+
2052
+ private static void flushFile (Object file , boolean useWriteUnraisable ) {
2053
+ if (!(file instanceof PNone )) {
2054
+ boolean closed = false ;
2055
+ try {
2056
+ closed = PyObjectIsTrueNode .executeUncached (PyObjectGetAttr .executeUncached (file , T_CLOSED ));
2057
+ } catch (PException e ) {
2058
+ // Ignore
2059
+ }
2060
+ if (!closed ) {
2061
+ try {
2062
+ PyObjectCallMethodObjArgs .executeUncached (file , T_FLUSH );
2063
+ } catch (PException e ) {
2064
+ if (useWriteUnraisable ) {
2065
+ WriteUnraisableNode .getUncached ().execute (e .getEscapedException (), null , null );
2066
+ }
2067
+ }
2068
+ }
2069
+ }
2070
+ }
2071
+
2032
2072
@ TruffleBoundary
2033
2073
public int getAtexitHookCount () {
2034
2074
return atExitHooks .size ();
0 commit comments