Jump to page: 1 2
Thread overview
Threading bugs
Jun 26, 2007
Tristam MacDonald
Jun 26, 2007
Tristam MacDonald
Jun 26, 2007
Johan Granberg
Jun 26, 2007
Tristam MacDonald
Jun 26, 2007
Johan Granberg
Jun 26, 2007
Tristam MacDonald
Jun 26, 2007
Johan Granberg
Jun 26, 2007
Tristam MacDonald
Jun 26, 2007
Johan Granberg
Jun 27, 2007
Sean Kelly
Jun 27, 2007
Sean Kelly
Jun 27, 2007
Tristam MacDonald
Jun 27, 2007
Sean Kelly
Jun 29, 2007
Myron Alexander
Jun 26, 2007
BCS
Jun 26, 2007
BCS
June 26, 2007
So, I am sure that I must be missing something simple, that is causing my multi-threading code in D fail miserably. I have cut it down to the smallest code sample that exhibits the problem, and I would be grateful if someone could have a look and let me know why...

import std.thread;
import std.stdio;

class Main
{
	this() {
		writefln("starting");

		Thread worker = new Thread(&workerMain);
		worker.start();
	}
	~this() {
		writefln("ending");
	}

	int workerMain()
	{
// -- disabled in case of deadlock in std.format, but never reached anyway
//		writefln("In Thread");
		return 0;
	}

	Thread worker;
}

int main()
{
	Main m = new Main();

	return 0;
}




June 26, 2007
And score 10 for forgetting to explain the problem :)

Anyway, this code sample should print "starting", star a thread that exits immediately, and finally print "ending" as the destructor is called at program termination.
Instead, it prints "starting" and then does nothing - or more precisely hogs the entirety of only one of my 2 cores - and never exits.

BTW, this is using gdc on a Mac (latest release of gdcmac), so could be a pthread specific problem perhaps?

Tristam MacDonald Wrote:

> So, I am sure that I must be missing something simple, that is causing my multi-threading code in D fail miserably. I have cut it down to the smallest code sample that exhibits the problem, and I would be grateful if someone could have a look and let me know why...
> 
> import std.thread;
> import std.stdio;
> 
> class Main
> {
> 	this() {
> 		writefln("starting");
> 
> 		Thread worker = new Thread(&workerMain);
> 		worker.start();
> 	}
> 	~this() {
> 		writefln("ending");
> 	}
> 
> 	int workerMain()
> 	{
> // -- disabled in case of deadlock in std.format, but never reached anyway
> //		writefln("In Thread");
> 		return 0;
> 	}
> 
> 	Thread worker;
> }
> 
> int main()
> {
> 	Main m = new Main();
> 
> 	return 0;
> }
> 
> 
> 

June 26, 2007
Reply to Tristam,

> So, I am sure that I must be missing something simple, that is causing
> my multi-threading code in D fail miserably. I have cut it down to the
> smallest code sample that exhibits the problem, and I would be
> grateful if someone could have a look and let me know why...
> 
> import std.thread;
> import std.stdio;
> class Main
> {
> this() {
> writefln("starting");
> Thread worker = new Thread(&workerMain);
> worker.start();
> }
> ~this() {
> writefln("ending");
> }
> int workerMain()
> {
> // -- disabled in case of deadlock in std.format, but never reached
> anyway
> //		writefln("In Thread");
> return 0;
> }
> Thread worker;
> }
> int main()
> {
> Main m = new Main();
> return 0;
> }

If I had to guess, I'd say that the program is exiting before the thread starts. But then I'm also guessing what the problem is.


June 26, 2007
Reply to Benjamin,

>  But then I'm also guessing what the problem is.
> 


scrath that


June 26, 2007
Tristam MacDonald wrote:

> And score 10 for forgetting to explain the problem :)
> 
> Anyway, this code sample should print "starting", star a thread that exits immediately, and finally print "ending" as the destructor is called at program termination. Instead, it prints "starting" and then does nothing - or more precisely hogs the entirety of only one of my 2 cores - and never exits.
> 
> BTW, this is using gdc on a Mac (latest release of gdcmac), so could be a pthread specific problem perhaps?
> 
> Tristam MacDonald Wrote:
> 
>> So, I am sure that I must be missing something simple, that is causing my multi-threading code in D fail miserably. I have cut it down to the smallest code sample that exhibits the problem, and I would be grateful if someone could have a look and let me know why...
>> 
>> import std.thread;
>> import std.stdio;
>> 
>> class Main
>> {
>> this() {
>> writefln("starting");
>> 
>> Thread worker = new Thread(&workerMain);
>> worker.start();
>> }
>> ~this() {
>> writefln("ending");
>> }
>> 
>> int workerMain()
>> {
>> // -- disabled in case of deadlock in std.format, but never reached
>> anyway
>> //           writefln("In Thread");
>> return 0;
>> }
>> 
>> Thread worker;
>> }
>> 
>> int main()
>> {
>> Main m = new Main();
>> 
>> return 0;
>> }
>> 
>> 
>>

If you change the main method to this the thread will be run.

int main()
{
        Main m = new Main();

        foreach(t;Thread.getAll())
                if(!t.isSelf())
                        t.wait();

        return 0;
}

The current behavior seams to be that all threads exits when main returns (or when std.c.stdlib.exit is run). The constructor is not run because the class is not deleted by you or the garbage collector, there was talk about this behavior some time ago (maybe last summer) and this is by design, search the newsgroup or changelog if you want to follow the discussion.
June 26, 2007
Hmm, I don't see anything relevant in either the changelog or the news group (haven't finished searching the latter though).

I am not sure I understand, shouldn't all remaining objects have their destructors called when the program exits? What would happen if the object had a non trivial destructor (dispose of shared memory, flush an iostream, etc.)?

The point I don't understand, is why is this only the case when I am using threads? And I think the thread implementation may be a little buggy here anyway, why on earth would the assert statement below cause a 'Bus Error'?

class Main
{
	this() {
		writefln("starting");

		Thread worker = new Thread(&workerMain);
		worker.start();
	}
	~this() {
		writefln("ending");
	}

	int workerMain()
	{
		writefln("In Thread");
		return 0;
	}

	Thread worker;
}

int main()
{
	Main m = new Main();

	assert(m.worker.getState() == Thread.TS.TERMINATED, "Thread not done!");

	return 0;
}

Johan Granberg Wrote:

> Tristam MacDonald wrote:
> 
> > And score 10 for forgetting to explain the problem :)
> > 
> > Anyway, this code sample should print "starting", star a thread that exits immediately, and finally print "ending" as the destructor is called at program termination. Instead, it prints "starting" and then does nothing - or more precisely hogs the entirety of only one of my 2 cores - and never exits.
> > 
> > BTW, this is using gdc on a Mac (latest release of gdcmac), so could be a pthread specific problem perhaps?
> > 
> > Tristam MacDonald Wrote:
> > 
> >> So, I am sure that I must be missing something simple, that is causing my multi-threading code in D fail miserably. I have cut it down to the smallest code sample that exhibits the problem, and I would be grateful if someone could have a look and let me know why...
> >> 
> >> import std.thread;
> >> import std.stdio;
> >> 
> >> class Main
> >> {
> >> this() {
> >> writefln("starting");
> >> 
> >> Thread worker = new Thread(&workerMain);
> >> worker.start();
> >> }
> >> ~this() {
> >> writefln("ending");
> >> }
> >> 
> >> int workerMain()
> >> {
> >> // -- disabled in case of deadlock in std.format, but never reached
> >> anyway
> >> //           writefln("In Thread");
> >> return 0;
> >> }
> >> 
> >> Thread worker;
> >> }
> >> 
> >> int main()
> >> {
> >> Main m = new Main();
> >> 
> >> return 0;
> >> }
> >> 
> >> 
> >>
> 
> If you change the main method to this the thread will be run.
> 
> int main()
> {
>         Main m = new Main();
> 
>         foreach(t;Thread.getAll())
>                 if(!t.isSelf())
>                         t.wait();
> 
>         return 0;
> }
> 
> The current behavior seams to be that all threads exits when main returns (or when std.c.stdlib.exit is run). The constructor is not run because the class is not deleted by you or the garbage collector, there was talk about this behavior some time ago (maybe last summer) and this is by design, search the newsgroup or changelog if you want to follow the discussion.



June 26, 2007
Tristam MacDonald wrote:

> Hmm, I don't see anything relevant in either the changelog or the news group (haven't finished searching the latter though).
> 
> I am not sure I understand, shouldn't all remaining objects have their destructors called when the program exits? What would happen if the object had a non trivial destructor (dispose of shared memory, flush an iostream, etc.)?
> 
> The point I don't understand, is why is this only the case when I am using threads? And I think the thread implementation may be a little buggy here anyway, why on earth would the assert statement below cause a 'Bus Error'?

Because you are redeclaring worker in the Main constructor, change this line
 Thread worker = new Thread(&workerMain);
to this
 worker = new Thread(&workerMain);

and it will probably work.

> class Main
> {
> this() {
> writefln("starting");
> 
> Thread worker = new Thread(&workerMain);
> worker.start();
> }
> ~this() {
> writefln("ending");
> }
> 
> int workerMain()
> {
> writefln("In Thread");
> return 0;
> }
> 
> Thread worker;
> }
> 
> int main()
> {
> Main m = new Main();
> 
> assert(m.worker.getState() == Thread.TS.TERMINATED, "Thread not done!");
> 
> return 0;
> }

June 26, 2007
Oh cripes, right, with that fixed your wait solution works fine, but I still can't find why destructors are not  called at termination with threads?

Johan Granberg Wrote:

> Tristam MacDonald wrote:
> 
> > Hmm, I don't see anything relevant in either the changelog or the news group (haven't finished searching the latter though).
> > 
> > I am not sure I understand, shouldn't all remaining objects have their destructors called when the program exits? What would happen if the object had a non trivial destructor (dispose of shared memory, flush an iostream, etc.)?
> > 
> > The point I don't understand, is why is this only the case when I am using threads? And I think the thread implementation may be a little buggy here anyway, why on earth would the assert statement below cause a 'Bus Error'?
> 
> Because you are redeclaring worker in the Main constructor, change this line
>  Thread worker = new Thread(&workerMain);
> to this
>  worker = new Thread(&workerMain);
> 
> and it will probably work.
> 
> > class Main
> > {
> > this() {
> > writefln("starting");
> > 
> > Thread worker = new Thread(&workerMain);
> > worker.start();
> > }
> > ~this() {
> > writefln("ending");
> > }
> > 
> > int workerMain()
> > {
> > writefln("In Thread");
> > return 0;
> > }
> > 
> > Thread worker;
> > }
> > 
> > int main()
> > {
> > Main m = new Main();
> > 
> > assert(m.worker.getState() == Thread.TS.TERMINATED, "Thread not done!");
> > 
> > return 0;
> > }
> 

June 26, 2007
Tristam MacDonald wrote:

> Oh cripes, right, with that fixed your wait solution works fine, but I still can't find why destructors are not  called at termination with threads?

An old newsgroup post by Walter http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=11455 i don't like this behavior myself but that's it.

> Johan Granberg Wrote:
> 
>> Tristam MacDonald wrote:
>> 
>> > Hmm, I don't see anything relevant in either the changelog or the news group (haven't finished searching the latter though).
>> > 
>> > I am not sure I understand, shouldn't all remaining objects have their destructors called when the program exits? What would happen if the object had a non trivial destructor (dispose of shared memory, flush an iostream, etc.)?
>> > 
>> > The point I don't understand, is why is this only the case when I am using threads? And I think the thread implementation may be a little buggy here anyway, why on earth would the assert statement below cause a 'Bus Error'?
>> 
>> Because you are redeclaring worker in the Main constructor, change this
>> line
>>  Thread worker = new Thread(&workerMain);
>> to this
>>  worker = new Thread(&workerMain);
>> 
>> and it will probably work.
>> 
>> > class Main
>> > {
>> > this() {
>> > writefln("starting");
>> > 
>> > Thread worker = new Thread(&workerMain);
>> > worker.start();
>> > }
>> > ~this() {
>> > writefln("ending");
>> > }
>> > 
>> > int workerMain()
>> > {
>> > writefln("In Thread");
>> > return 0;
>> > }
>> > 
>> > Thread worker;
>> > }
>> > 
>> > int main()
>> > {
>> > Main m = new Main();
>> > 
>> > assert(m.worker.getState() == Thread.TS.TERMINATED, "Thread not
>> > done!");
>> > 
>> > return 0;
>> > }
>>

June 26, 2007
Would explicitly running a full collect cycle at the end of main (and wrapping logic in an inner function work around this? More likely some would still be left though.

Johan Granberg Wrote:

> Tristam MacDonald wrote:
> 
> > Oh cripes, right, with that fixed your wait solution works fine, but I still can't find why destructors are not  called at termination with threads?
> 
> An old newsgroup post by Walter http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=11455 i don't like this behavior myself but that's it.
> 
> > Johan Granberg Wrote:
> > 
> >> Tristam MacDonald wrote:
> >> 
> >> > Hmm, I don't see anything relevant in either the changelog or the news group (haven't finished searching the latter though).
> >> > 
> >> > I am not sure I understand, shouldn't all remaining objects have their destructors called when the program exits? What would happen if the object had a non trivial destructor (dispose of shared memory, flush an iostream, etc.)?
> >> > 
> >> > The point I don't understand, is why is this only the case when I am using threads? And I think the thread implementation may be a little buggy here anyway, why on earth would the assert statement below cause a 'Bus Error'?
> >> 
> >> Because you are redeclaring worker in the Main constructor, change this
> >> line
> >>  Thread worker = new Thread(&workerMain);
> >> to this
> >>  worker = new Thread(&workerMain);
> >> 
> >> and it will probably work.
> >> 
> >> > class Main
> >> > {
> >> > this() {
> >> > writefln("starting");
> >> > 
> >> > Thread worker = new Thread(&workerMain);
> >> > worker.start();
> >> > }
> >> > ~this() {
> >> > writefln("ending");
> >> > }
> >> > 
> >> > int workerMain()
> >> > {
> >> > writefln("In Thread");
> >> > return 0;
> >> > }
> >> > 
> >> > Thread worker;
> >> > }
> >> > 
> >> > int main()
> >> > {
> >> > Main m = new Main();
> >> > 
> >> > assert(m.worker.getState() == Thread.TS.TERMINATED, "Thread not
> >> > done!");
> >> > 
> >> > return 0;
> >> > }
> >>
> 

« First   ‹ Prev
1 2