[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#400960: marked as done (libc6-i686: Thread cancelation while in pthread_cond_wait corrupts condition variable)



Your message dated Wed, 18 Apr 2007 18:07:01 +0200
with message-id <20070418160651.GA30205@i386.aurel32.net>
and subject line libc6-i686: Thread cancelation while in pthread_cond_wait corrupts condition variable
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--- Begin Message ---
Package: libc6-i686
Version: 2.3.6.ds1-8
Severity: normal


If a thread is canceled while waiting for a condition in
pthread_cond_wait(), the used condition variable is left in a
corrupted state. For example calling pthread_cond_destroy() on it will
fail. Moreover, the canceled thread does not properly lock the
associated mutex before running any cleanup handlers.

See the attached example program.

The specific combination that shows the problem is:
libc6-i686 and linux-image-2.6.18-3-686 (either the debian kernel package or a vanilla kernel)

If either libc6-i686 is removed or a 2.6.17 kernel is used the problem
goes away. Another way to make it go away is to set
LD_ASSUME_KERNEL=2.4.19. It appears that the broken combination is
NPTL with kernel 2.6.18 or later.

-- System Information:
Debian Release: 4.0
  APT prefers unstable
  APT policy: (800, 'unstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-3-686
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages libc6-i686 depends on:
ii  libc6                        2.3.6.ds1-8 GNU C Library: Shared libraries

libc6-i686 recommends no packages.

-- debconf-show failed
/* Test program for pthread cancelation while waiting on a condition variable.

Expected output:
action: locking mutex
action: got mutex
Condition false, going to sleep.
cleanup_hook for action: unlocking  mutex
action: unlocked  mutex

Output in the case of kernel 2.6.18-3 and libc6-i686:
action: locking mutex
action: got mutex
Condition false, going to sleep.
cleanup_hook for action: unlocking  mutex
cleanup_hook: error unlocking mutex: Operation not permitted
action: unlocked  mutex
main: Wave Condition error Device or resource busy

*/

#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <assert.h>

static int resource_ready = 0;

static  pthread_t thread;
static pthread_attr_t ta;
static pthread_mutex_t mutex;
static pthread_mutexattr_t mt_attr;
static pthread_cond_t condition;

#define DEBUG 1
#define es_log(level, args ... ) printf(args); printf("\n");

/* <Mutex helpers */

/* Helper functions and macros for managing mutexes */
#ifndef DEBUG
#define MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex);
#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex);
#else
#define MUTEX_LOCK(mutex) \
  if (pthread_mutex_lock(&mutex) != 0) \
{\
  es_log(2, "%s: Error locking mutex.", __func__); \
  exit(3); \
}

#define MUTEX_UNLOCK(mutex) \
  { \
int ret_;\
  if ((ret_ = pthread_mutex_unlock(&mutex)) != 0) \
{\
  es_log(2, "%s: error unlocking mutex: %s", __func__, strerror(ret_)); \
  } \
}
#endif

static void cleanup_hook(void *function_name) {
  es_log(2, "cleanup_hook for %s: unlocking  mutex", function_name);
  MUTEX_UNLOCK(mutex);
  es_log(2, "%s: unlocked  mutex", (char *) function_name);
}

#define DO_UNLOCK \
  es_log(2, "%s: unlocking mutex", __func__); \
  MUTEX_UNLOCK(mutex); \
  pthread_cleanup_pop(0); \
  es_log(2, "%s: unlocked mutex", __func__);

#define DO_LOCK \
  es_log(2, "%s: locking mutex", __func__); \
  pthread_cleanup_push(cleanup_hook, (void *) __func__); \
  MUTEX_LOCK(mutex); \
  es_log(2, "%s: got mutex", __func__); \
  pthread_testcancel();

/* > */





static void *action(void* arg) {
  DO_LOCK;
  while (!resource_ready) {
	printf("Condition false, going to sleep.\n");
	pthread_cond_wait(&condition, &mutex);
	printf("Woke up, going to test condition.\n");
  }
  printf("Condition passed..\n");
  DO_UNLOCK;
  return 0;
}

int main() {
  int ret; 
  /* Initialize thread, mutex and condition */
	pthread_mutexattr_init(&mt_attr);
#ifdef DEBUG
	pthread_mutexattr_settype(&mt_attr, PTHREAD_MUTEX_ERRORCHECK_NP);
#endif
	pthread_mutex_init(&mutex, &mt_attr);

	pthread_cond_init(&condition, NULL);
	
  /* Start thread*/
	pthread_attr_init(&ta);
	pthread_create(&thread, &ta, action, NULL);

  /* Wait for thread to go to sleep on condition */
	sleep(3);

	/*Cancel thread */
	
	pthread_cancel(thread);

	/* Join thread */
	ret = pthread_join(thread, NULL);
	assert(ret == 0);
	/* At this point, no other thread is running */

	ret = pthread_mutex_trylock(&mutex);
	if (ret != 0) {
	  printf("main: trylock error: %s", strerror(ret));
	}

ret = pthread_cond_destroy(&condition);
  if (ret)
  {
	es_log(2, "main: Wave Condition error %s", strerror(ret));
  }
	
	return 0;
}

--- End Message ---
--- Begin Message ---
Version: 2.5-1

On Wed, Nov 29, 2006 at 09:30:15PM +0100, Lukas Loehrer wrote:
> Package: libc6-i686
> Version: 2.3.6.ds1-8
> Severity: normal
> 
> 
> If a thread is canceled while waiting for a condition in
> pthread_cond_wait(), the used condition variable is left in a
> corrupted state. For example calling pthread_cond_destroy() on it will
> fail. Moreover, the canceled thread does not properly lock the
> associated mutex before running any cleanup handlers.
> 
> See the attached example program.
> 
> The specific combination that shows the problem is:
> libc6-i686 and linux-image-2.6.18-3-686 (either the debian kernel package or a vanilla kernel)
> 
> If either libc6-i686 is removed or a 2.6.17 kernel is used the problem
> goes away. Another way to make it go away is to set
> LD_ASSUME_KERNEL=2.4.19. It appears that the broken combination is
> NPTL with kernel 2.6.18 or later.
> 

The bug has been fixed in glibc version 2.5-1. Closing the bug.

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

--- End Message ---

Reply to: