winpr-thread:
- added the unit test: TestThreadExitThread - fix: ensure thread_list to be up to date before to call ExitThread() - possibly resolved: Problems with serial redirection #2389
This commit is contained in:
parent
7a1485a2e4
commit
6f5de27081
@ -6,7 +6,8 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestThreadCommandLineToArgv.c
|
||||
TestThreadCreateProcess.c)
|
||||
TestThreadCreateProcess.c
|
||||
TestThreadExitThread.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
|
53
winpr/libwinpr/thread/test/TestThreadExitThread.c
Normal file
53
winpr/libwinpr/thread/test/TestThreadExitThread.c
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright © 2015 Hewlett-Packard Development Company, L.P.
|
||||
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
static void* thread_func(void* arg)
|
||||
{
|
||||
/* exists of the thread the quickest as possible */
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int TestThreadExitThread(int argc, char* argv[])
|
||||
{
|
||||
HANDLE thread;
|
||||
QWORD waitResult;
|
||||
int i;
|
||||
|
||||
/* FIXME: create some noise to better guaranty the test validity and
|
||||
* decrease the number of loops */
|
||||
for (i=0; i<10000; i++)
|
||||
{
|
||||
thread = CreateThread(NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE)thread_func,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (thread == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fprintf(stderr, "Got an invalid thread!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
waitResult = WaitForSingleObject(thread, 1000);
|
||||
if (waitResult != WAIT_OBJECT_0)
|
||||
{
|
||||
/* When the thread exits before the internal thread_list
|
||||
* was updated, ExitThread() is not able to retrieve the
|
||||
* related WINPR_THREAD object and is not able to signal
|
||||
* the end of the thread. Therefore WaitForSingleObject
|
||||
* never get the signal.
|
||||
*/
|
||||
fprintf(stderr, "Didn't quit the main thread correctly\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
CloseHandle(thread);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -294,6 +294,18 @@ static void* thread_launcher(void* arg)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* pthread_create(3) doesn't guaranty the thread ID to be set
|
||||
* before to invoke the start_routine() even if this seems to be
|
||||
* actually done.*/
|
||||
thread->thread = pthread_self();
|
||||
|
||||
/* also done by winpr_StartThread(). This ensures thread_list
|
||||
* was updated before the thread could exit */
|
||||
if (!ListDictionary_Add(thread_list, &thread->thread, thread))
|
||||
{
|
||||
WLog_ERR(TAG, "Thread function argument is %p", fkt);
|
||||
goto exit;
|
||||
}
|
||||
rc = fkt(thread->lpParameter);
|
||||
}
|
||||
|
||||
@ -328,7 +340,7 @@ static BOOL winpr_StartThread(WINPR_THREAD *thread)
|
||||
|
||||
if (pthread_create(&thread->thread, &attr, thread_launcher, thread))
|
||||
goto error;
|
||||
if (!ListDictionary_Add(thread_list, &thread->thread, thread))
|
||||
if (!ListDictionary_Add(thread_list, &thread->thread, thread)) /* also done by thread_launcher() */
|
||||
goto error;
|
||||
pthread_attr_destroy(&attr);
|
||||
dump_thread(thread);
|
||||
|
Loading…
Reference in New Issue
Block a user