ethrbunny has asked for the wisdom of the Perl Monks concerning the following question:

Im trying to use cond_timedwait to determine whether a given thread is 'stuck'. Im doing something wrong as I don't seem to get a timeout.

#!/usr/bin/perl -w use threads; use threads::shared; my $locked : shared; lock( $locked ); print "locked(main)\n "; $thr = async{ test() }; print "starting\n"; $wait = cond_timedwait( $locked, time() + 5 ); print "result: timeout\n" if ( !defined( $wait )); print "done\n"; exit; sub test { print "started. \n"; lock( $locked ); print "locked(test)\n "; sleep( 10 ); print "exiting\n"; cond_signal( $locked ); }

Outputs the following:
locked(main) starting started. locked(test) exiting result: timeout done
If the thread sleeps for 5 and the timer waits for 10 then it seems to signal properly and exit. Its the 'stuck' case (thread sleeps for 10, timer waits for 5) that doesn't seem to work as I would expect it to.

What am I doing wrong?

Replies are listed 'Best First'.
Re: threads - cond_timedwait question
by Khen1950fx (Canon) on Dec 31, 2009 at 21:07 UTC
    This worked for me:
    #!/usr/bin/perl - use strict; use warnings; use threads; use threads::shared; my $locked :shared; lock($locked); print "locked(main)\n "; my $thr = async( sub { test() } ); print "starting\n"; my $wait = time() + 15; until ( my $ok = lock($locked) ) { last if !cond_timedwait( $locked, $wait ); } print "result: timeout\n" if defined $wait; print "done\n"; exit; sub test { print "started. \n"; lock($locked); print "lock(test)\n "; sleep 10; print "exiting\n"; { no warnings 'threads'; cond_signal($locked); } }
      Now suppose that 'test' was a wedged thread.
      1. Change the 'sleep 10' in 'test' to 'sleep 30'.
      2. Change the 'time() + 15' to 'time() + 5'.
      3. Add a 'print "waiting\n"' before the 'last' statement.


      I would expect the 'cond_timedwait' statement to return after 5 seconds and loop over the 'print ..' statement 5-6 times before the 'test' thread returned. Instead I see the 'test' thread start and block the loop until 'test' finishes.

      Am I completely misunderstanding how this process works?
        FWIW: this appears to work at detecting a 'stopped' job.
        #!/usr/bin/perl -w use threads; use Thread::Semaphore; $mtx = new Thread::Semaphore(2); $thr0 = async{ test() }; $thr1 = async{ timer( ) }; print "starting\n"; sleep(1); $v = $mtx->down(); print "test finished 1st\n" if ( $v == 2 ); print "timer finished 1st\n" if ( $v == 1 ); $thr0->detach(); $thr1->detach(); sub test { print " start(test)\n"; my $d = $mtx->down(); sleep( 5 ); $mtx->up( 3 ); print " exit(test)\n"; } sub timer { print " start(timer)\n"; my $d = $mtx->down(); sleep( 10 ); $mtx->up( 2 ); print " exit(timer)\n"; } start(test) starting start(timer) exit(test) test finished 1st
        Unfortunately this also gives me a 'A thread exited while 2 threads were running.' message at the end. I don't know how big of an issue this is.