www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Thread join behaviour

reply Russel Winder <russel winder.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I thought the following would terminate gracefully having printed 0..9
in some (random) order:

        #! /usr/bin/env rdmd
       =20
        import std.algorithm ;
        import std.range ;
        import std.stdio ;
        import core.thread ;
       =20
        int main ( immutable string[] args ) {
          auto threads =3D map ! ( ( int a ) {
              void delegate ( ) f ( ) {
                return delegate ( ) { writeln ( a ) ; } ;=20
              }
              return new Thread ( f )  ;
            } ) ( iota ( 10 ) ) ;
          foreach ( t ; threads ) { t.start ( ) ; }
          foreach ( t ; threads ) { t.join ( ) ; }
          return 0 ;
        }

However, this does not happen, at least with 2.059 on Linux as per
Debian Unstable.  Instead I get:

        1
        2
        4
        5
        8
        3
        7
        6
        9
        0
        core.thread.ThreadException src/core/thread.d(906): Unable to join =
thread
        ----------------
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(_Dmain+0x83) [0x425edb]
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern (C) int rt.dmain2=
.main(int, char**).void runMain()+0x17) [0x429bab]
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern (C) int rt.dmain2=
.main(int, char**).void tryExec(scope void delegate())+0x23) [0x42952b]
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern (C) int rt.dmain2=
.main(int, char**).void runAll()+0x3d) [0x429bf9]
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern (C) int rt.dmain2=
.main(int, char**).void tryExec(scope void delegate())+0x23) [0x42952b]
        /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initi=
alizingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(main+0xd3) [0x4294c3]
        /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd) [0x7f1ed17f=
8ead]
        ----------------

I think I must be having a dumb moment as my reaction continues to be
WTF.

--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
Apr 14 2012
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 14-04-2012 18:04, Russel Winder wrote:
 I thought the following would terminate gracefully having printed 0..9
 in some (random) order:

          #! /usr/bin/env rdmd

          import std.algorithm ;
          import std.range ;
          import std.stdio ;
          import core.thread ;

          int main ( immutable string[] args ) {
            auto threads = map ! ( ( int a ) {
                void delegate ( ) f ( ) {
                  return delegate ( ) { writeln ( a ) ; } ;
                }
                return new Thread ( f )  ;
              } ) ( iota ( 10 ) ) ;
            foreach ( t ; threads ) { t.start ( ) ; }
            foreach ( t ; threads ) { t.join ( ) ; }
            return 0 ;
          }

 However, this does not happen, at least with 2.059 on Linux as per
 Debian Unstable.  Instead I get:

          1
          2
          4
          5
          8
          3
          7
          6
          9
          0
          core.thread.ThreadException src/core/thread.d(906): Unable to join
thread
          ----------------
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AE
B96D0D(_Dmain+0x83) [0x425edb]
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2..main(int, char**).void runMain()+0x17)
[0x429bab]
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2..main(int, char**).void tryExec(scope
void delegate())+0x23) [0x42952b]
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2..main(int, char**).void runAll()+0x3d)
[0x429bf9]
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2..main(int, char**).void tryExec(scope
void delegate())+0x23) [0x42952b]
          /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9
EAB96D0D(main+0xd3) [0x4294c3]
          /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)
[0x7f1ed17f8ead]
          ----------------

 I think I must be having a dumb moment as my reaction continues to be
 WTF.

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_join.3.html#ERRORS We can rule out these: EDEADLK: Can't happen with your code. EINVAL (second case): No other thread is trying to join. ESRCH: Shouldn't happen since druntime registers threads with libpthread. So, the first case of EINVAL (thread is not a joinable thread) must be the cause. I have no clue *why* though... -- - Alex
Apr 14 2012
parent Matt Soucy <msoucy csh.rit.edu> writes:
On 04/14/2012 04:56 PM, Alex Rønne Petersen wrote:
 On 14-04-2012 18:04, Russel Winder wrote:
 I thought the following would terminate gracefully having printed 0..9
 in some (random) order:

 #! /usr/bin/env rdmd

 import std.algorithm ;
 import std.range ;
 import std.stdio ;
 import core.thread ;

 int main ( immutable string[] args ) {
 auto threads = map ! ( ( int a ) {
 void delegate ( ) f ( ) {
 return delegate ( ) { writeln ( a ) ; } ;
 }
 return new Thread ( f ) ;
 } ) ( iota ( 10 ) ) ;
 foreach ( t ; threads ) { t.start ( ) ; }
 foreach ( t ; threads ) { t.join ( ) ; }
 return 0 ;
 }

 However, this does not happen, at least with 2.059 on Linux as per
 Debian Unstable. Instead I get:

 1
 2
 4
 5
 8
 3
 7
 6
 9
 0
 core.thread.ThreadException src/core/thread.d(906): Unable to join thread
 ----------------
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(_Dmain+0x83)
 [0x425edb]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern
 (C) int rt.dmain2..main(int, char**).void runMain()+0x17) [0x429bab]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern
 (C) int rt.dmain2..main(int, char**).void tryExec(scope void
 delegate())+0x23) [0x42952b]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern
 (C) int rt.dmain2..main(int, char**).void runAll()+0x3d) [0x429bf9]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(extern
 (C) int rt.dmain2..main(int, char**).void tryExec(scope void
 delegate())+0x23) [0x42952b]
 /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AEAB96D0D(main+0xd3)
 [0x4294c3]
 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd) [0x7f1ed17f8ead]
 ----------------

 I think I must be having a dumb moment as my reaction continues to be
 WTF.

http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_join.3.html#ERRORS We can rule out these: EDEADLK: Can't happen with your code. EINVAL (second case): No other thread is trying to join. ESRCH: Shouldn't happen since druntime registers threads with libpthread. So, the first case of EINVAL (thread is not a joinable thread) must be the cause. I have no clue *why* though...

it doesn't have this issue. Also, when I run your code repeatedly the number of successful numbers printed changes a lot. I'm assuming that you're trying to join a thread that already exited... -Matt
Apr 14 2012
prev sibling next sibling parent Somedude <lovelydear mailmetrash.com> writes:
Le 14/04/2012 18:04, Russel Winder a écrit :
 I thought the following would terminate gracefully having printed 0..9
 in some (random) order:
 
         #! /usr/bin/env rdmd
         
         import std.algorithm ;
         import std.range ;
         import std.stdio ;
         import core.thread ;
         
         int main ( immutable string[] args ) {
           auto threads = map ! ( ( int a ) {
               void delegate ( ) f ( ) {
                 return delegate ( ) { writeln ( a ) ; } ; 
               }
               return new Thread ( f )  ;
             } ) ( iota ( 10 ) ) ;
           foreach ( t ; threads ) { t.start ( ) ; }
           foreach ( t ; threads ) { t.join ( ) ; }
           return 0 ;
         }
 
 However, this does not happen, at least with 2.059 on Linux as per
 Debian Unstable.  Instead I get:
 
         1
         2
         4
         5
         8
         3
         7
         6
         9
         0
         core.thread.ThreadException src/core/thread.d(906): Unable to join
thread
         ----------------
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9AE
B96D0D(_Dmain+0x83) [0x425edb]
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2.main(int, char**).void runMain()+0x17)
[0x429bab]
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void
delegate())+0x23) [0x42952b]
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2.main(int, char**).void runAll()+0x3d)
[0x429bf9]
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F1
3A9AEAB96D0D(extern (C) int rt.dmain2.main(int, char**).void tryExec(scope void
delegate())+0x23) [0x42952b]
         /tmp/.rdmd-1000/home/users/russel/Progs/OddsByLanguage/D/Odds/initializingWithAMap.d.9532BBED12C814F25F173A9
EAB96D0D(main+0xd3) [0x4294c3]
         /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)
[0x7f1ed17f8ead]
         ----------------
 
 I think I must be having a dumb moment as my reaction continues to be
 WTF.
 

This works: int main ( immutable string[] args ) { auto threadgroup = new ThreadGroup(); void delegate ( ) f (int a ) { return delegate ( ) { writeln ( a ) ; } ; } for ( int n = 0; n < 10; n++ ) { threadgroup.create(f(n)); } threadgroup.joinAll( ); return 0 ; } Threads are tracked by the threadgroup, which knows who can be joined.
Apr 14 2012
prev sibling next sibling parent Russel Winder <russel winder.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sat, 2012-04-14 at 17:10 -0400, Matt Soucy wrote:
[...]
 If you merge the two foreach loops into one, doing t.start();t.join();=

 it doesn't have this issue. Also, when I run your code repeatedly the=20
 number of successful numbers printed changes a lot.
 I'm assuming that you're trying to join a thread that already exited...

This matches with Artur's comment about laziness/strictness, but doing the above is only useful for experimentation, it cannot be a final solution since it enforces serialization of thread execution. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Apr 15 2012
prev sibling parent Russel Winder <russel winder.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sat, 2012-04-14 at 23:27 +0200, Somedude wrote:
[...]
 This works:
=20
 int main ( immutable string[] args ) {
=20
   auto threadgroup =3D new ThreadGroup();
=20
   void delegate ( ) f (int a ) {
     return delegate ( ) { writeln ( a ) ; } ;
   }
=20
   for ( int n =3D 0; n < 10; n++ ) {
     threadgroup.create(f(n));
   }
   threadgroup.joinAll( );
   return 0 ;
 }
=20
 Threads are tracked by the threadgroup, which knows who can be joined.

Thanks for this, a useful alternative realization. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Apr 15 2012