www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Child threads orphaned if main thread exits

reply Mike Swieton <mike swieton.net> writes:
I've discovered what is probably a bug, and rather un-handy at the very least,
with D's threading. If main() returns before a child thread, a crash is very
likely. I believe that this is because the garbage collector is closed (see
the gc_term call in dmain2.d) after main() closes. This is a problem because
child threads may still be active.

This could probably be fixed with something like:

foreach (Thread t; allThreads) if (t!==null) t.wait();

in a static dtor in thread.d, though I am not sure whether this is a good idea
or not. The below example has been tested under linux and segfaults probably
around half the time.

import std.thread;

extern (C) int sleep(uint);

int main(char[][] args) {
	class A {
		bool finished1, finished2;

		int i;

		this()  { printf("creating A\n"); }
		~this() { printf("Destroying A\n"); }

		synchronized int doSomething1() {
			// force main thread to not wait. The error can still occur, but
			// manifests more often if I force it.
			finished1 = 1;

			for (i=0; i<5; i++) {
				printf("1: setting %d\n", i);
				sleep(1);
			}

			printf("returning from 1\n");
			return 0;
		}

		synchronized int doSomething2() {
			finished2 = 1;

			for (i=0; i<5; i++) {
				printf("2: setting %d\n", i);
				sleep(1);
			}

			printf("returning from 2\n");
			return 0;
		}
	} // A

	A a = new A();
	Thread t1 = new Thread(&a.doSomething1);
	Thread t2 = new Thread(&a.doSomething2);

	t1.start();
	t2.start();

	while (!a.finished1 && !a.finished2)
	{
		Thread.yield();
		printf("Main waiting...\n");
		sleep(1);
	}

	// Uncommenting the below lines will make it work
	//t1.wait();
	//t2.wait();

	return 0;
}

Mike Swieton
__
It's so simple to be wise. Just think of something stupid to say and then
don't say it.
	- Sam Levenson
May 09 2004
parent Mike Swieton <Mike_member pathlink.com> writes:
In article <pan.2004.05.09.23.23.00.195300 swieton.net>, Mike Swieton says...
I've discovered what is probably a bug, and rather un-handy at the very least,
with D's threading. If main() returns before a child thread, a crash is very
likely. I believe that this is because the garbage collector is closed (see
the gc_term call in dmain2.d) after main() closes. This is a problem because
child threads may still be active.
I have written a patch to the dmain2.d file for this, see attached. Consider this patch public domain. I'm not sure if there is a compelling reason not to do this, but it seems reasonable. It also appears to be what Java does. Mike Swieton __ U.S. schools create sheeple. - John Kaminski begin 0644 dmain2.d-threadwait.diff M+2TM(&1M86EN,BYD"3(P,#0M,#4M,#8 ,C$Z,S,Z,#0N,#`P,#`P,#`P("TP M-#`P"BLK*R`O:&]M92]S=VEE=&]N+V1M86EN,BYD"3(P,#0M,#4M,#D ,C`Z M-#$Z,#(N,#`P,#`P,#`P("TP-#`P"D!`("TT+#8 *S0L."!`0`H :6UP;W)T M('-T9"YC+G-T9&QI8CL-"B!I;7!O<G0 <W1D+G-T<FEN9SL-"B`-"BMI;7!O M<G0 <W1D+G1H<F5A9#L-"BL-"B!E>'1E<FX *$,I('9O:60 7U-425]M;VYI M=&]R7W-T871I8V-T;W(H*3L-"B!E>'1E<FX *$,I('9O:60 7U-41%]M;VYI M=&]R7W-T871I8V1T;W(H*3L-"B!E>'1E<FX *$,I('9O:60 7U-425]C<FET M:6-A;%]I;FET*"D[#0I`0"`M-C4L-B`K-C<L,3 0$`*(`EA<F=S(#T 86U; M,"`N+B!A<F=C73L-"B`-"B`)<F5S=6QT(#T ;6%I;BAA<F=S*3L-"BL-"BL) M9F]R96%C:"AI;G0 :61X+"!4:')E860 =#L 5&AR96%D+F=E=$%L;" I*0T* M*PE[#0HK"0ET<GD-"BL)"7L-"BL)"0EI9B`H="`F)B!T("$]/2!4:')E860N M9V5T5&AI<R I*0T**PD)"0ET+G=A:70H*3L-"BL)"7T 8V%T8V *%1H<F5A M9$5R<F]R(&5X*2![#0HK"0D)<')I;G1F*")4:')E860 97)R;W(Z("(I.PT* M*PD)"65X+G!R:6YT*"D[#0HK"0E]#0HK"7T-"B` ("` ?0T*("` ("!C871C 6:"`H3V)J96-T(&\I#0H ("` ('L-" HK ` end
May 09 2004