semaphores and handle leaks

Morgan McLeod mmcleod@nrao.edu
Tue Dec 5 23:12:00 GMT 2006


Hello again.

Below is C++ code for a fairly simple program which exhibits the 
apparent handle leaks I described in my previous posting.   I linked 
this with the standard STL rather than STLPort and it makes no 
difference.   This is compiled to an EXE, not a DLL like my real 
application.

Again, please feel free to point out if I'm doing somethign wrong.

Thanks

-Morgan McLeod
Software Engineer
National Radio Astronomy Observatory
Charlottesville, Va


#include <stdio.h>
#include <windows.h>
#include <pthread.h>
#include <semaphore.h>
#include <list>

struct listElem {
    int num;
    sem_t *synchLock;
   
    listElem(int _num, sem_t *_synchLock)
      : num(_num),
        synchLock(_synchLock)
        {}

    ~listElem()
      {}
};

typedef std::list<listElem> semList_t;
semList_t list1;
semList_t list2;

// mutexes to protect the lists:
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;

// flags to tell the threads to stop:
bool shutdownNow;
bool shutdownDone1;
bool shutdownDone2;

// thread 1 processes list1:
void *thread1(void *arg) {
    while (true) {
        if (shutdownNow) {
            shutdownDone1 = true;
            pthread_exit(NULL);
        }      
        pthread_mutex_lock(&mutex1);
        if (list1.empty())
            pthread_mutex_unlock(&mutex1);
       
        else {       
            // remove the front element from the list:
            listElem E = list1.front();
            list1.pop_front();
            pthread_mutex_unlock(&mutex1);
           
            // save the original semaphore:
            sem_t *sem1 = E.synchLock;
           
            // create and initialize a new semaphore.
            // substitute it for the original:
            sem_t sem2;
            E.synchLock = &sem2;
            sem_init(E.synchLock, 0, 0);
           
            // put the item in list2 for processing by thread2:
            pthread_mutex_lock(&mutex2);
            list2.push_back(E);
            pthread_mutex_unlock(&mutex2);
           
            // Wait on, then destroy the substitute semaphore:
            sem_wait(E.synchLock);
            sem_destroy(E.synchLock);
           
            // put back and post on the original semaphore:
            E.synchLock = sem1;
            sem_post(E.synchLock);

            printf("thread1: %d done\n", E.num);
        }
        Sleep(10);
    }
}

// thread2 processes list2:
void *thread2(void *arg) {
    while (true) {
        if (shutdownNow) {
            shutdownDone2 = true;
            pthread_exit(NULL);
        }      
        pthread_mutex_lock(&mutex2);
        if (list2.empty())
            pthread_mutex_unlock(&mutex2);
       
        else {
            listElem E = list2.front();
            list2.pop_front();
            pthread_mutex_unlock(&mutex2);
           
            sem_post(E.synchLock);

            printf("thread2: %d done\n", E.num);
        }
        Sleep(10);
    }
}

const int COUNT = 1000;

int main(int, char*[]) {
    // Initialize flags:
    shutdownNow = shutdownDone1 = shutdownDone2 = false;
   
    // Pause to look at Task Manager.  Handles = 8:
    Sleep(5000);

    pthread_mutex_init(&mutex1, NULL);
    pthread_mutex_init(&mutex2, NULL);
   
    sem_t synchLocks[COUNT];
   
    for (int index = 0; index < COUNT; ++index) {
        sem_init(&synchLocks[index], 0, 0);
        listElem E(index, &synchLocks[index]);
        list1.push_back(E);
    }

    // Handles = 2019.  Starts to leak...

    pthread_t T1;
    pthread_create(&T1, NULL, thread1, NULL);   

    pthread_t T2;
    pthread_create(&T2, NULL, thread2, NULL);   
   
    while (!list1.empty() || !list2.empty())
        Sleep(10);
   
    // Pause to look at Task Manager.  Handles = 2261 (varies):
    Sleep(5000);
   
    shutdownNow = true;
    while (!shutdownDone1 && !shutdownDone2)
        Sleep(10);

    for (int index = 0; index < COUNT; ++index)
        sem_destroy(&synchLocks[index]);

    pthread_mutex_destroy(&mutex1);
    pthread_mutex_destroy(&mutex2);

    // Pause to look at Task Manager.  Handles = 264 (varies):
    Sleep(5000);
   
    printf("done\n");   
    return 0;
}








More information about the Pthreads-win32 mailing list