@@ -148,17 +148,25 @@ extern (C) __gshared bool rt_trapExceptions = true;
148
148
149
149
alias void delegate (Throwable) ExceptionHandler;
150
150
151
+ /**
152
+ * Keep track of how often rt_init/rt_term were called.
153
+ */
154
+ shared size_t _initCount;
155
+
151
156
/* *********************************************
152
157
* Initialize druntime.
153
158
* If a C program wishes to call D code, and there's no D main(), then it
154
159
* must call rt_init() and rt_term().
155
- * If it fails, call dg. Except that what dg might be
156
- * able to do is undetermined, since the state of druntime
157
- * will not be known.
158
- * This needs rethinking.
159
160
*/
160
- extern (C ) bool rt_init(ExceptionHandler dg = null )
161
+ extern (C ) int rt_init()
161
162
{
163
+ /* @@BUG 11380 @@ Need to synchronize rt_init/rt_term calls for
164
+ version (Shared) druntime, because multiple C threads might
165
+ initialize different D libraries without knowing about the
166
+ shared druntime. Also we need to attach any thread that calls
167
+ rt_init. */
168
+ if (_initCount++ ) return 1 ;
169
+
162
170
_STI_monitor_staticctor();
163
171
_STI_critical_init();
164
172
@@ -169,68 +177,45 @@ extern (C) bool rt_init(ExceptionHandler dg = null)
169
177
initStaticDataGC();
170
178
rt_moduleCtor();
171
179
rt_moduleTlsCtor();
172
- return true ;
180
+ return 1 ;
173
181
}
174
- catch (Throwable e )
182
+ catch (Throwable t )
175
183
{
176
- /* Note that if we get here, the runtime is in an unknown state.
177
- * I'm not sure what the point of calling dg is.
178
- */
179
- if (dg)
180
- dg(e);
181
- else
182
- throw e; // rethrow, don't silently ignore error
183
- /* Rethrow, and the two STD functions aren't called?
184
- * This needs rethinking.
185
- */
184
+ _initCount = 0 ;
185
+ printThrowable(t);
186
186
}
187
187
_STD_critical_term();
188
188
_STD_monitor_staticdtor();
189
- return false ;
189
+ return 0 ;
190
190
}
191
191
192
192
/* *********************************************
193
193
* Terminate use of druntime.
194
- * If it fails, call dg. Except that what dg might be
195
- * able to do is undetermined, since the state of druntime
196
- * will not be known.
197
- * This needs rethinking.
198
194
*/
199
- extern (C ) bool rt_term(ExceptionHandler dg = null )
195
+ extern (C ) int rt_term()
200
196
{
197
+ if (! _initCount) return 0 ; // was never initialized
198
+ if (-- _initCount) return 1 ;
199
+
201
200
try
202
201
{
203
- /* Check that all other non-daemon threads have finished
204
- * execution before calling the shared module destructors.
205
- * Calling thread_joinAll here would be too late because other
206
- * shared libraries might have already been
207
- * destructed/unloaded.
208
- */
209
- import core.thread : Thread ;
210
- auto tthis = Thread .getThis();
211
- foreach (t; Thread )
212
- {
213
- if (t ! is tthis && t.isRunning && ! t.isDaemon)
214
- assert (0 , " Can only call rt_term when all non-daemon threads have been joined or detached." );
215
- }
216
-
217
202
rt_moduleTlsDtor();
203
+ thread_joinAll();
218
204
rt_moduleDtor();
219
205
gc_term();
220
206
finiSections();
221
- return true ;
207
+ return 1 ;
222
208
}
223
- catch (Throwable e )
209
+ catch (Throwable t )
224
210
{
225
- if (dg)
226
- dg(e);
211
+ printThrowable(t);
227
212
}
228
213
finally
229
214
{
230
215
_STD_critical_term();
231
216
_STD_monitor_staticdtor();
232
217
}
233
- return false ;
218
+ return 0 ;
234
219
}
235
220
236
221
/* **********************************
@@ -392,29 +377,6 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc)
392
377
393
378
void tryExec (scope void delegate () dg)
394
379
{
395
- static void print (Throwable t)
396
- {
397
- void sink (const (char )[] buf) nothrow
398
- {
399
- printf(" %.*s" , cast (int )buf.length, buf.ptr);
400
- }
401
-
402
- for (; t; t = t.next)
403
- {
404
- t.toString(&sink); sink (" \n " );
405
-
406
- auto e = cast (Error)t;
407
- if (e is null || e.bypassedException is null ) continue ;
408
-
409
- sink(" === Bypassed ===\n " );
410
- for (auto t2 = e.bypassedException; t2; t2 = t2.next)
411
- {
412
- t2.toString(&sink); sink (" \n " );
413
- }
414
- sink(" === ~Bypassed ===\n " );
415
- }
416
- }
417
-
418
380
if (trapExceptions)
419
381
{
420
382
try
@@ -423,7 +385,7 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc)
423
385
}
424
386
catch (Throwable t)
425
387
{
426
- print (t);
388
+ printThrowable (t);
427
389
result = EXIT_FAILURE ;
428
390
}
429
391
}
@@ -441,33 +403,18 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc)
441
403
// the user's main function. If main terminates with an exception,
442
404
// the exception is handled and then cleanup begins. An exception
443
405
// thrown during cleanup, however, will abort the cleanup process.
444
- void runMain ()
445
- {
446
- if (runModuleUnitTests())
447
- tryExec({ result = mainFunc(args); });
448
- else
449
- result = EXIT_FAILURE ;
450
-
451
- tryExec({thread_joinAll();});
452
- }
453
-
454
- void runMainWithInit ()
406
+ void runAll ()
455
407
{
456
408
if (rt_init() && runModuleUnitTests())
457
409
tryExec({ result = mainFunc(args); });
458
410
else
459
411
result = EXIT_FAILURE ;
460
412
461
- tryExec({thread_joinAll();});
462
-
463
413
if (! rt_term())
464
414
result = (result == EXIT_SUCCESS ) ? EXIT_FAILURE : result;
465
415
}
466
416
467
- version (linux ) // initialization is done in rt.sections_linux
468
- tryExec(&runMain);
469
- else
470
- tryExec(&runMainWithInit);
417
+ tryExec(&runAll);
471
418
472
419
// Issue 10344: flush stdout and return nonzero on failure
473
420
if (.fflush(.stdout) != 0 )
@@ -481,3 +428,26 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc)
481
428
482
429
return result;
483
430
}
431
+
432
+ private void printThrowable (Throwable t)
433
+ {
434
+ void sink (const (char )[] buf) nothrow
435
+ {
436
+ printf(" %.*s" , cast (int )buf.length, buf.ptr);
437
+ }
438
+
439
+ for (; t; t = t.next)
440
+ {
441
+ t.toString(&sink); sink (" \n " );
442
+
443
+ auto e = cast (Error)t;
444
+ if (e is null || e.bypassedException is null ) continue ;
445
+
446
+ sink(" === Bypassed ===\n " );
447
+ for (auto t2 = e.bypassedException; t2; t2 = t2.next)
448
+ {
449
+ t2.toString(&sink); sink (" \n " );
450
+ }
451
+ sink(" === ~Bypassed ===\n " );
452
+ }
453
+ }
0 commit comments