@@ -82,9 +82,19 @@ public ContextQueue(Engine engine, String name, Configuration conf, Logger logge
8282 this .modulesReplacements = modulesReplacements ;
8383 this .OPTS = OPTS ;
8484
85- // Pre-populate pool
85+ // Pre-populate pool: each Context must be created on a platform thread.
86+ // Do NOT delegate to newContext() here -- its callers (args(), create())
87+ // are already inside onPlatformThread, so newContext() must not wrap again
88+ // (nested dispatch creates the Context on a *different* platform thread
89+ // than the one that will enter it, which corrupts Truffle's
90+ // DefaultContextThreadLocal bookkeeping, see oracle/graal#7520).
8691 for (var c = 0 ;c < POOL_SIZE ;c ++) {
87- pool .offer (newContext ());
92+ try {
93+ pool .offer (PolyglotThreadUtils .onPlatformThread (
94+ () -> newContext (engine , name , conf , logger , mclient , modulesReplacements , OPTS )));
95+ } catch (Exception e ) {
96+ LOGGER .warn ("Error pre-creating polyglot context" , e );
97+ }
8898 }
8999 }
90100
@@ -134,20 +144,23 @@ private void release(Context ctx) {
134144 * @throws Exception if the task throws an exception
135145 */
136146 public <T > T executeWithContext (ContextTask <T > task ) throws Exception {
137- Context ctx = acquire ();
138- try {
139- // Context.enter()/leave() must run on a platform thread, see PolyglotThreadUtils
140- return PolyglotThreadUtils .onPlatformThread (() -> {
147+ // acquire/enter/task/leave/release must all happen on the very same
148+ // platform thread: if the pool is empty, acquire() calls newContext()
149+ // which creates a Context that must be entered on the same thread
150+ // (see PolyglotThreadUtils / oracle/graal#7520).
151+ return PolyglotThreadUtils .onPlatformThread (() -> {
152+ Context ctx = acquire ();
153+ try {
141154 ctx .enter ();
142155 try {
143156 return task .run (ctx );
144157 } finally {
145158 ctx .leave ();
146159 }
147- });
148- } finally {
149- release ( ctx );
150- }
160+ } finally {
161+ release ( ctx );
162+ }
163+ });
151164 }
152165
153166 /**
@@ -157,21 +170,20 @@ public <T> T executeWithContext(ContextTask<T> task) throws Exception {
157170 * @throws Exception if the task throws an exception
158171 */
159172 public void executeWithContext (VoidContextTask task ) throws Exception {
160- Context ctx = acquire ();
161- try {
162- // Context.enter()/leave() must run on a platform thread, see PolyglotThreadUtils
163- PolyglotThreadUtils .onPlatformThread (() -> {
173+ PolyglotThreadUtils .onPlatformThread (() -> {
174+ Context ctx = acquire ();
175+ try {
164176 ctx .enter ();
165177 try {
166178 task .run (ctx );
167179 } finally {
168180 ctx .leave ();
169181 }
170- return null ;
171- } );
172- } finally {
173- release ( ctx ) ;
174- }
182+ } finally {
183+ release ( ctx );
184+ }
185+ return null ;
186+ });
175187 }
176188
177189 /**
@@ -238,28 +250,19 @@ public static Context newContext(Engine engine, String name, Configuration conf,
238250 LOGGER .trace ("modules-replacements ignored (removed in GraalVM 25.1): {}" , modulesReplacements );
239251 }
240252
241- try {
242- // Context creation touches thread locals, must run on a platform thread, see PolyglotThreadUtils
243- return PolyglotThreadUtils .onPlatformThread (() -> {
244- var ctx = Context .newBuilder ().engine (engine )
245- .allowAllAccess (true )
246- .allowHostAccess (HostAccess .ALL )
247- .allowHostClassLookup (className -> true )
248- .allowIO (IOAccess .ALL )
249- .allowExperimentalOptions (true )
250- .allowValueSharing (true ) // Enable value sharing to reduce marshalling overhead
251- .options (OPTS )
252- .build ();
253+ var ctx = Context .newBuilder ().engine (engine )
254+ .allowAllAccess (true )
255+ .allowHostAccess (HostAccess .ALL )
256+ .allowHostClassLookup (className -> true )
257+ .allowIO (IOAccess .ALL )
258+ .allowExperimentalOptions (true )
259+ .allowValueSharing (true ) // Enable value sharing to reduce marshalling overhead
260+ .options (OPTS )
261+ .build ();
253262
254- addBindings (ctx , name , conf , logger , mclient );
263+ addBindings (ctx , name , conf , logger , mclient );
255264
256- return ctx ;
257- });
258- } catch (RuntimeException re ) {
259- throw re ;
260- } catch (Exception e ) {
261- throw new IllegalStateException ("Error creating polyglot context" , e );
262- }
265+ return ctx ;
263266 }
264267
265268 private static void addBindings (Context ctx ,
0 commit comments