May 09, 2004
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 10, 2004
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