www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Indeterminate thread behavior?

reply Georg Wrede <Georg_member pathlink.com> writes:
I can run the following, usually once, and on the following 
runs it (usually!) segfaults before finish. If I do something
else and then run it, it again runs fine the first time only.

I ran this on RedHat-9.

# import std.thread;
#
#
# int foo(void *ptr)
# {
#     for(int i=5000;i>0;i--) {
#       printf("foo....................%d\n");
#     }
#     return 0;
# }
#
# int bar(void *ptr)
# {
#     for(int i=5000;i>0;i--) {
#       printf("bar-----------------------------------------%d\n");
#     }
#     return 0;
# }
#
#
# void main()
# {
#     Thread t1 = new Thread(&foo, null);
#
#     Thread t2 = new Thread(&bar, null);
#
#
#     t1.start();
#     t2.start();
#
#     while(t1.getState() == std.thread.Thread.TS.RUNNING)
#         Thread.yield ();
# }

Obviously, foo and bar don't yield, main only checks for t1,
no threads are stopped, no errors are caught. 
Still, indeterminate behavior is not what I'd expect.

Makes no difference whether I run it like

$ ./ttest
$ ./ttest > /tmp/ttest.lst
$ ./ttest | tee /tmp/ttest.lst

But running it with the same command again makes it segfault.
(If you have a new computer you might have to increase the
loop count, to maybe 50000, so that the first thread doesn't
always finish before the second starts.)

---------------------

Another thing: the Thread class is not well documented in the 
docs. Even trivial things like Arrays are meticulously 
explained with lots of examples, but Threads don't have a 
single example code there!!

---------------------

Oh, and in case you haven't already tried the above, there's
a typo in both printf statements. So change

#       printf("foo....................%d\n");
to
#       printf("foo....................%d\n",i);

in both places.

Now, the really interesting part (this is slightly off-topic,
but I couldn't help myself): with the above faulty printf
statements, the code ran exactly the same!!!! So we have ESP
inbuilt in D -- it understands what you meant to write!  :-)

Maybe I should file a bug report about checking the arguments
to printf at compile time? At least for literal format strings.
Dec 10 2004
next sibling parent Phill Thorpe <phill pacific.net.au> writes:
On Fri, 10 Dec 2004 12:08:19 +0000, Georg Wrede wrote:

 I can run the following, usually once, and on the following 
 runs it (usually!) segfaults before finish. If I do something
 else and then run it, it again runs fine the first time only.
 
 I ran this on RedHat-9.
 
 # import std.thread;
 #
 #
 # int foo(void *ptr)
 # {
 #     for(int i=5000;i>0;i--) {
 #       printf("foo....................%d\n");
 #     }
 #     return 0;
 # }
 #
 # int bar(void *ptr)
 # {
 #     for(int i=5000;i>0;i--) {
 #       printf("bar-----------------------------------------%d\n");
 #     }
 #     return 0;
 # }
 #
 #
 # void main()
 # {
 #     Thread t1 = new Thread(&foo, null);
 #
 #     Thread t2 = new Thread(&bar, null);
 #
 #
 #     t1.start();
 #     t2.start();
 #
 #     while(t1.getState() == std.thread.Thread.TS.RUNNING)
 #         Thread.yield ();
 # }
 
 Obviously, foo and bar don't yield, main only checks for t1,
 no threads are stopped, no errors are caught. 
 Still, indeterminate behavior is not what I'd expect.
 
 Makes no difference whether I run it like
 
 $ ./ttest
 $ ./ttest > /tmp/ttest.lst
 $ ./ttest | tee /tmp/ttest.lst
 
 But running it with the same command again makes it segfault.
 (If you have a new computer you might have to increase the
 loop count, to maybe 50000, so that the first thread doesn't
 always finish before the second starts.)
 
 ---------------------
 
 Another thing: the Thread class is not well documented in the 
 docs. Even trivial things like Arrays are meticulously 
 explained with lots of examples, but Threads don't have a 
 single example code there!!
 
 ---------------------
 
 Oh, and in case you haven't already tried the above, there's
 a typo in both printf statements. So change
 
 #       printf("foo....................%d\n");
 to
 #       printf("foo....................%d\n",i);
 
 in both places.
 
 Now, the really interesting part (this is slightly off-topic,
 but I couldn't help myself): with the above faulty printf
 statements, the code ran exactly the same!!!! So we have ESP
 inbuilt in D -- it understands what you meant to write!  :-)
 
 Maybe I should file a bug report about checking the arguments
 to printf at compile time? At least for literal format strings.

I thought that there was nothing wrong with either printf statments, except that the %d is a waste of time. Phill.
Dec 12 2004
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Georg Wrede" <Georg_member pathlink.com> wrote in message 
news:cpc3jj$12m8$1 digitaldaemon.com...
I can run the following, usually once, and on the following
 runs it (usually!) segfaults before finish. If I do something
 else and then run it, it again runs fine the first time only.

 I ran this on RedHat-9.

 # import std.thread;
 #
 #
 # int foo(void *ptr)
 # {
 #     for(int i=5000;i>0;i--) {
 #       printf("foo....................%d\n");
 #     }
 #     return 0;
 # }
 #
 # int bar(void *ptr)
 # {
 #     for(int i=5000;i>0;i--) {
 #       printf("bar-----------------------------------------%d\n");
 #     }
 #     return 0;
 # }
 #
 #
 # void main()
 # {
 #     Thread t1 = new Thread(&foo, null);
 #
 #     Thread t2 = new Thread(&bar, null);
 #
 #
 #     t1.start();
 #     t2.start();
 #
 #     while(t1.getState() == std.thread.Thread.TS.RUNNING)
 #         Thread.yield ();
 # }

 Obviously, foo and bar don't yield, main only checks for t1,
 no threads are stopped, no errors are caught.
 Still, indeterminate behavior is not what I'd expect.

 Makes no difference whether I run it like

 $ ./ttest
 $ ./ttest > /tmp/ttest.lst
 $ ./ttest | tee /tmp/ttest.lst

 But running it with the same command again makes it segfault.
 (If you have a new computer you might have to increase the
 loop count, to maybe 50000, so that the first thread doesn't
 always finish before the second starts.)

 ---------------------

 Another thing: the Thread class is not well documented in the
 docs. Even trivial things like Arrays are meticulously
 explained with lots of examples, but Threads don't have a
 single example code there!!

 ---------------------

 Oh, and in case you haven't already tried the above, there's
 a typo in both printf statements. So change

 #       printf("foo....................%d\n");
 to
 #       printf("foo....................%d\n",i);

 in both places.

 Now, the really interesting part (this is slightly off-topic,
 but I couldn't help myself): with the above faulty printf
 statements, the code ran exactly the same!!!! So we have ESP
 inbuilt in D -- it understands what you meant to write!  :-)

 Maybe I should file a bug report about checking the arguments
 to printf at compile time? At least for literal format strings.

Try making sure all the threads are done before the end of your main function. If some threads are still running it can cause seg-v's I believe. There are some pieces of D's threading behavior that I think should be tightened up - like how to treat threads that are still running after main exits. -Ben
Dec 12 2004
parent Georg Wrede <Georg_member pathlink.com> writes:
In article <cphhuc$206e$1 digitaldaemon.com>, Ben Hinkle says...
"Georg Wrede" <Georg_member pathlink.com> wrote in message 
news:cpc3jj$12m8$1 digitaldaemon.com...
I can run the following, usually once, and on the following
 runs it (usually!) segfaults before finish. If I do something

Try making sure all the threads are done before the end of your main function. If some threads are still running it can cause seg-v's I believe. There are some pieces of D's threading behavior that I think should be tightened up - like how to treat threads that are still running after main exits.

Thanks! That seems to correct the problem. I inserted # t1.wait(); # t2.wait(); at the very end of main.
Dec 12 2004