bug-glibc
[Top][All Lists]
Advanced

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

basic_string fails on MP Linux machine


From: Maciek Kozyrczak
Subject: basic_string fails on MP Linux machine
Date: Wed, 08 Nov 2000 12:20:31 -0500

Hi,

I seem to have confirmed that the basic_string class in the C++ library
is not thread safe.  I was worried about the calls to
string::Rep::grab()
on the static "nilRep" object during string costruction.  The referece
count
in the Rep data structure is not guarded by a lock, so it may get out of
sunc with actual uses of the string in multiple threads.  Bad things
happen
when string::Rep::release() is called on "nilRep" when its referece
count
is messed up.

Conditions for reproducing this bug:

1) Compile this code with:
   
   g++ -Wall -O0 -ggdb libtest.cxx -static -lpthread

   Static linking of pthread is essential, as is the -O0 flag.

2) Run this cade on a multi-prcessor machine running Linux Red Hat 7.0.

   Tool Versions (RPM):
        gcc-2.96-54
        gcc-c++-2.96-54
        glibc-2.1.94-3
        glibc-devel-2.1.94-3

   I am using a dual-processor Dell PowerEdge 1300.

   I have not been able to reproduce this bug on a uniprocessor.
   Either it takes too long for the right scheduling combination to
   happen, or there is something with thread scheduling on a
   uniprocessor that prevents threads from simultaneously incrementing
   the ref count and leaving it in bad state.


I'm including the code that reproduces the bug.  As is, the program
should
never terminate.  Acutally, the program dies with an error message
similar to this:

Thread #0 starting
Thread #0 forked
Thread #1 forked
Thread #1 starting
Thread #1: length = 134955868
Thread #0: length = 134955868
Thread #2 forked
Thread #2 starting
Thread #2: length = 134955868

Regards,
Maciek Kozyrczak
address@hidden

//*****************************************************************************
// The bug-causing code
//*****************************************************************************

#define _REENTRANT
#define _THREAD_SAFE
#define _PTHREADS
#define _POSIX_THREADS
#define _POSIX_THREAD_SAFE_FUNCTIONS

#include <cerrno>
#include <string>
using namespace std;

extern "C" {
#include <pthread.h>
#include <time.h>
}

//*****************************************************************************

// Lock for cerr
pthread_mutex_t cerr_lock = PTHREAD_MUTEX_INITIALIZER;

//*****************************************************************************

void *
handler(void *args)
{
  int thr_num = (int)args;

  pthread_mutex_lock(&cerr_lock);
  cerr << "Thread #" << thr_num << " starting" << endl;
  pthread_mutex_unlock(&cerr_lock);

  //  pthread_mutex_t sleep_lock = PTHREAD_MUTEX_INITIALIZER;
  //  pthread_cond_t sleep_cond = PTHREAD_COND_INITIALIZER;

  while (1) {
    string foo;

    if (foo.length() != 0) {
      pthread_mutex_lock(&cerr_lock);
      cerr << "Thread #" << thr_num << ": length = " << foo.length() <<
endl;
      pthread_mutex_unlock(&cerr_lock);
      exit (1);
    }
  }

  return (void*)0;
}

//*****************************************************************************

int
main(int argc, char *argv[])
{
  int i;

  // Fork some threads.
  // The total number of threads running in the program is going to be
4.
  for (i = 0; i < 99; i++) {
    // Fork a child thread to execute the work of the handler
    pthread_t child_thread;
    while (1) {
      pthread_attr_t child_attr;
      pthread_attr_init(&child_attr);
      pthread_attr_setdetachstate(&child_attr,PTHREAD_CREATE_DETACHED);
      int rc =
pthread_create(&child_thread,&child_attr,handler,(void*)i);
      if (rc == 0) break;
      if (rc == EAGAIN) continue;
      // Error in the thread fork.
      cerr << __FILE__ << ":" << __LINE__ << ": Error forking thread" <<
endl;
      exit(1);
    }
    pthread_mutex_lock(&cerr_lock);
    cerr << "Thread #" << i << " forked" << endl;
    pthread_mutex_unlock(&cerr_lock);
  }

  // Get the main thread executing the same handler function.
  handler((void*)i);

  // Sanity check
  cerr << "Done with main()" << endl;

  return 0;
}

//*****************************************************************************



reply via email to

[Prev in Thread] Current Thread [Next in Thread]