Here's and example code. I know it must be the line with pthread_cleanup_push() because the errors cease when I comment out this one line: EXTERN_C DWORD naiBeginThread( LPVOID pSecurity, UINT unStackSize, void (*pfStartAddr)(void *), void *pArgs, UINT nInitFlag, LPDWORD pdwThreadID) { naiHandleObject_t *hThread; int nThreadID; // Create the thread object if ( (hThread = (naiHandleObject_t *)malloc(sizeof(naiHandleObject_t))) == NULL) { nErrno = ENOMEM; return((DWORD)(-1)); } if ( (hThread->Handle = (void *)malloc(sizeof(naiThread_t))) == NULL) { nErrno = ENOMEM; free(hThread); return((DWORD)(-1)); } // Start the thread and set all the outbound data if ( (nThreadID = pthread_create((naiThread_t *)hThread->Handle,NULL, (void *(*) (void *)) pfStartAddr, pArgs)) != 0) { free(hThread->Handle); free(hThread); return((DWORD)(-1)); } // Push on the clean up routines - memory is freed by naiCleanupThread() naiThreadCleanup_t *pCleanup; if ( (pCleanup = (naiThreadCleanup_t *) malloc(sizeof(naiThreadCleanup_t))) == NULL) return((DWORD)(-1)); pCleanup->Mutex = hThread->Mutex; pCleanup->Condition = hThread->Condition; pCleanup->bSignalled = &(hThread->bSignalled); pthread_cleanup_push(naiCleanupThread,(void *)pCleanup); // The caller must deal with this and convert it to HANDLE type if (pdwThreadID != NULL) { *pdwThreadID = nThreadID; } hThread->nType = naiOBJECT_THREAD; hThread->nReferenceCounter = 1; if (pthread_cond_init(&hThread->Condition,NULL) != 0) { free(hThread->Handle); free(hThread); return((DWORD)(-1)); } if (pthread_mutex_init(&hThread->Mutex,NULL) != 0) { free(hThread->Handle); free(hThread); return((DWORD)(-1)); } hThread->bSignalled = naiFALSE; return((DWORD)hThread); } //------------------------------------------------------------------------- --- // Just like naiBeginThread() with the exceptions noted in the docs for that // function. EXTERN_C HANDLE naiCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { HANDLE *Handle; DWORD dwRet; if ( (dwRet = naiBeginThread((LPVOID)lpThreadAttributes,dwStackSize, ( void (*) (void *) )lpStartAddress, (void *)lpParameter,dwCreationFlags, lpThreadId)) == -1) { return(NULL); } memcpy(&Handle,&dwRet,4); return(Handle); } //------------------------------------------------------------------------- --- Here are the compiler errors that are generated (BTW, the code above starts with line 1133): gcc -c -fPIC -g -D_LINUX_REDHAT -I./source -I./include -I../source - I../include -I../../linux/source -I../linux/include -I../../linux/source - I../../linux/include -I../../source -I../../include - o ../linux/bin/portable.o ../../linux/source/portable.cpp ../../linux/source/portable.cpp: In function `DWORD naiBeginThread (void *, unsigned int, void (*) (void *), void *, unsigned int, long unsigned int *)': ../../linux/source/portable.cpp:1172: parse error before string constant ../../linux/source/portable.cpp:1184: `lpThreadAttributes' undeclared (first use this function) ../../linux/source/portable.cpp:1184: (Each undeclared identifier is reported only once for each function it appears in.) ../../linux/source/portable.cpp:1184: `dwStackSize' undeclared (first use this function) ../../linux/source/portable.cpp:1185: `lpStartAddress' undeclared (first use this function) ../../linux/source/portable.cpp:1186: `lpParameter' undeclared (first use this function) ../../linux/source/portable.cpp:1186: `dwCreationFlags' undeclared (first use this function) ../../linux/source/portable.cpp:1187: `lpThreadId' undeclared (first use this function) ../../linux/source/portable.cpp:1189: warning: return to non-pointer type `DWORD' from NULL ../../linux/source/portable.cpp:1189: warning: argument to non-pointer type `long unsigned int' from NULL ../../linux/source/portable.cpp:1191: `Handle' undeclared (first use this function)
This is a bug in the code you're trying to compile. Citing pthread.h: /* Install a cleanup handler: ROUTINE will be called with arguments ARG when the thread is cancelled or calls pthread_exit. ROUTINE will also be called with arguments ARG when the matching pthread_cleanup_pop is executed with non-zero EXECUTE argument. pthread_cleanup_push and pthread_cleanup_pop are macros and must always be used in matching pairs at the same nesting level of braces. */ You don't have the corresponding pthread_cleanup_pop macro and those must be used in pairs at the same nesting level. Also, I'd recommend doing something with the returns if they should be in the same pthread cleanup region (because pushing cleanup and forgetting to pop it is a bug).