NO

Author Topic: Bug in cnd_signal() of threads.h, with a test example  (Read 2179 times)

neo313

  • Guest
Bug in cnd_signal() of threads.h, with a test example
« on: March 09, 2014, 12:48:39 am »
I have discovered a bug when using cnd_signal() to signal a thread.

cnd_signal() works fine until you signal twice or more in the same critical section. Then the code comes to a dead lock; the thread that sends the signal comes to a stop in the mtx_lock() in the next iterations, while the receiver thread waits for a signal in cnd_wait(). All functions will return thrd_success.

You should be able to call cnd_signal() as many times as you want. As per documentation:
If no threads are blocked, does nothing and returns thrd_success. http://en.cppreference.com/w/c/thread/cnd_signal
If no threads are blocked on the condition variable at the time of the call, the function does nothing and return success. pelles docs


Notes:
-calling cnd_broadcast() after two cnd_signal() will trigger an exception.
-replacing cnd_signal() with cnd_broadcast(), will remove the bug
-pthread_cond_signal() from pthreads has similar description in docs http://linux.die.net/man/3/pthread_cond_signal
-optimization level doesn't matter
-mutex type doesn't matter

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>
#include <assert.h>

#define BUG_ENABLE //disable to get correct behaviour

//#define cnd_signal cnd_broadcast //on the other hand, cnd_broadcast works fine

mtx_t mutex ;
cnd_t cond ;

int run = 0 ;
int unlock = 0 ;

int Test( void* data )
{
( void )data ;

int count = 0 ;
run = 1 ;
while( run )
{
int d = mtx_lock( &mutex ) ;
assert( d == thrd_success ) ;

unlock = 1 ;

d = cnd_wait( &cond , &mutex ) ;
assert( d == thrd_success ) ;

printf("AWAKE %d\n", count++ ) ;

d = mtx_unlock( &mutex ) ;
assert( d == thrd_success ) ;

thrd_yield() ;
}

return 0 ;
}

int main( void )
{

thrd_t thread ;

int d = mtx_init( &mutex , mtx_plain ) ;
assert( d == thrd_success ) ;
d = cnd_init( &cond ) ;
assert( d == thrd_success ) ;

d = thrd_create( &thread , Test , NULL ) ;
assert( d == thrd_success ) ;

while( run == 0 )
thrd_yield() ;

for( int c = 0 ; c < 1000 ; c++ )
{
while( unlock == 0 )
thrd_yield() ;

int d = mtx_lock( &mutex ) ;
assert( d == thrd_success ) ;

d = cnd_signal( &cond ) ;
assert( d == thrd_success ) ;

#ifdef BUG_ENABLE
d = cnd_signal( &cond ) ;
assert( d == thrd_success ) ;
#endif

unlock = 0 ;

d = mtx_unlock( &mutex ) ;
assert( d == thrd_success ) ;
}



printf("DONE\n") ;
while( 1 )
thrd_yield() ;

  return 0;
}



I would love to get a confirmation for this.

Thank you.

I have Win7 32 bit, pelles 7.00.355
« Last Edit: March 09, 2014, 05:31:18 am by neo313 »

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2084
    • http://www.smorgasbordet.com
Re: Bug in cnd_signal() of threads.h, with a test example
« Reply #1 on: April 12, 2014, 05:31:02 pm »
Should be fixed in v8.0, RC2.
/Pelle