diff --git a/client/X11/xf_interface.c b/client/X11/xf_interface.c index b99c6b9e6..d9d24528e 100644 --- a/client/X11/xf_interface.c +++ b/client/X11/xf_interface.c @@ -76,10 +76,6 @@ #include "xfreerdp.h" -HANDLE g_sem = NULL; -int g_thread_count = 0; -BYTE g_disconnect_reason = 0; - static long xv_port = 0; static const size_t password_size = 512; @@ -1023,19 +1019,19 @@ void xf_window_free(xfInfo* xfi) XFreeModifiermap(xfi->modifier_map); xfi->modifier_map = 0; - if (xfi->gc != NULL) + if (xfi->gc) { XFreeGC(xfi->display, xfi->gc); xfi->gc = 0; } - if (xfi->gc_mono != NULL) + if (xfi->gc_mono) { XFreeGC(xfi->display, xfi->gc_mono); xfi->gc_mono = 0; } - if (xfi->window != NULL) + if (xfi->window) { xf_DestroyWindow(xfi, xfi->window); xfi->window = NULL; @@ -1060,7 +1056,7 @@ void xf_window_free(xfInfo* xfi) xfi->image = NULL; } - if (context != NULL) + if (context) { cache_free(context->cache); context->cache = NULL; @@ -1207,7 +1203,7 @@ void* xf_channels_thread(void* arg) * @param instance - pointer to the rdp_freerdp structure that contains the session's settings * @return A code from the enum XF_EXIT_CODE (0 if successful) */ -int xfreerdp_run(freerdp* instance) +void* xf_thread(void* param) { int i; int fds; @@ -1215,14 +1211,15 @@ int xfreerdp_run(freerdp* instance) int max_fds; int rcount; int wcount; - int ret = 0; BOOL status; + int exit_code; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; + freerdp* instance; int fd_input_event; - HANDLE input_event = INVALID_HANDLE_VALUE; + HANDLE input_event; int select_status; BOOL async_update; BOOL async_input; @@ -1235,6 +1232,11 @@ int xfreerdp_run(freerdp* instance) rdpSettings* settings; struct timeval timeout; + exit_code = 0; + input_event = NULL; + + instance = (freerdp*) param; + ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); ZeroMemory(&timeout, sizeof(struct timeval)); @@ -1254,7 +1256,8 @@ int xfreerdp_run(freerdp* instance) if (!status) { xf_free(xfi); - return XF_EXIT_CONN_FAILED; + exit_code = XF_EXIT_CONN_FAILED; + ExitThread(exit_code); } channels = instance->context->channels; @@ -1290,7 +1293,7 @@ int xfreerdp_run(freerdp* instance) if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get FreeRDP file descriptor\n"); - ret = XF_EXIT_CONN_FAILED; + exit_code = XF_EXIT_CONN_FAILED; break; } } @@ -1300,7 +1303,7 @@ int xfreerdp_run(freerdp* instance) if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get channel manager file descriptor\n"); - ret = XF_EXIT_CONN_FAILED; + exit_code = XF_EXIT_CONN_FAILED; break; } } @@ -1310,7 +1313,7 @@ int xfreerdp_run(freerdp* instance) if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get xfreerdp file descriptor\n"); - ret = XF_EXIT_CONN_FAILED; + exit_code = XF_EXIT_CONN_FAILED; break; } } @@ -1441,8 +1444,8 @@ int xfreerdp_run(freerdp* instance) } } - if (!ret) - ret = freerdp_error_info(instance); + if (!exit_code) + exit_code = freerdp_error_info(instance); freerdp_channels_close(channels, instance); freerdp_channels_free(channels); @@ -1450,27 +1453,12 @@ int xfreerdp_run(freerdp* instance) gdi_free(instance); xf_free(xfi); - return ret; + ExitThread(exit_code); } -void* xf_thread_func(void* param) +DWORD xf_exit_code_from_disconnect_reason(DWORD reason) { - freerdp* instance = (freerdp*) param; - - g_disconnect_reason = xfreerdp_run(instance); - - g_thread_count--; - - if (g_thread_count < 1) - ReleaseSemaphore(g_sem, 1, NULL); - - pthread_exit(NULL); -} - -BYTE xf_exit_code_from_disconnect_reason(UINT32 reason) -{ - if (reason == 0 || - (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED)) + if (reason == 0 || (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED)) return reason; /* License error set */ diff --git a/client/X11/xf_interface.h b/client/X11/xf_interface.h index bba75c96d..38cf279e7 100644 --- a/client/X11/xf_interface.h +++ b/client/X11/xf_interface.h @@ -34,8 +34,8 @@ int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type); int xf_receive_channel_data(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size); -BYTE xf_exit_code_from_disconnect_reason(UINT32 reason); +DWORD xf_exit_code_from_disconnect_reason(DWORD reason); -void* xf_thread_func(void* param); +void* xf_thread(void* param); #endif /* __XF_INTERFACE_H */ diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index bfbcdeb6b..f55406191 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -40,13 +40,10 @@ #include "xfreerdp.h" -extern HANDLE g_sem; -extern int g_thread_count; -extern BYTE g_disconnect_reason; - int main(int argc, char* argv[]) { - pthread_t thread; + HANDLE thread; + DWORD dwExitCode; freerdp* instance; freerdp_handle_signals(); @@ -55,8 +52,6 @@ int main(int argc, char* argv[]) freerdp_channels_global_init(); - g_sem = CreateSemaphore(NULL, 0, 1, NULL); - instance = freerdp_new(); instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; @@ -74,21 +69,16 @@ int main(int argc, char* argv[]) instance->context->argv = argv; instance->settings->SoftwareGdi = FALSE; - g_thread_count++; - pthread_create(&thread, 0, xf_thread_func, instance); + thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread, (void*) instance, 0, NULL); - while (g_thread_count > 0) - { - WaitForSingleObject(g_sem, INFINITE); - } + WaitForSingleObject(thread, INFINITE); - pthread_join(thread, NULL); - pthread_detach(thread); + GetExitCodeThread(thread, &dwExitCode); freerdp_context_free(instance); freerdp_free(instance); freerdp_channels_global_uninit(); - return xf_exit_code_from_disconnect_reason(g_disconnect_reason); + return xf_exit_code_from_disconnect_reason(dwExitCode); } diff --git a/winpr/include/winpr/spec.h b/winpr/include/winpr/spec.h index 89c847d29..37b80f08f 100644 --- a/winpr/include/winpr/spec.h +++ b/winpr/include/winpr/spec.h @@ -20,23 +20,14 @@ #ifndef WINPR_SPEC_H #define WINPR_SPEC_H +#include + #ifdef _WIN32 #include #else -#if defined(__x86_64) && \ - !(defined(_X86_) || defined(__i386__) || defined(_IA64_)) -#if !defined(_AMD64_) -#define _AMD64_ -#endif -#endif /* _AMD64_ */ - -#ifdef _AMD64_ -#define _WIN64 -#endif - #ifndef DECLSPEC_ALIGN #if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(MIDL_PASS) #define DECLSPEC_ALIGN(x) __declspec(align(x)) @@ -47,7 +38,7 @@ #endif #endif /* DECLSPEC_ALIGN */ -#ifdef _WIN64 +#ifdef _M_AMD64 #define MEMORY_ALLOCATION_ALIGNMENT 16 #else #define MEMORY_ALLOCATION_ALIGNMENT 8 @@ -55,7 +46,19 @@ #define DUMMYSTRUCTNAME s +#ifdef __GNUC__ +#ifndef __declspec +#define __declspec(e) __attribute__((e)) +#endif +#endif + +#ifndef DECLSPEC_NORETURN +#if (defined(__GNUC__) || defined(_MSC_VER)) +#define DECLSPEC_NORETURN __declspec(noreturn) +#else #define DECLSPEC_NORETURN +#endif +#endif /* DECLSPEC_NORETURN */ #endif diff --git a/winpr/include/winpr/thread.h b/winpr/include/winpr/thread.h index 6f7610277..cf7d8a19b 100644 --- a/winpr/include/winpr/thread.h +++ b/winpr/include/winpr/thread.h @@ -23,6 +23,7 @@ #include #include +#include #include #ifndef _WIN32 @@ -105,7 +106,7 @@ WINPR_API BOOL CreateProcessAsUserW(HANDLE hToken, LPCWSTR lpApplicationName, LP #define CreateProcessAsUser CreateProcessAsUserA #endif -WINPR_API VOID ExitProcess(UINT uExitCode); +DECLSPEC_NORETURN WINPR_API VOID ExitProcess(UINT uExitCode); WINPR_API HANDLE _GetCurrentProcess(VOID); WINPR_API DWORD GetCurrentProcessId(VOID); @@ -123,7 +124,8 @@ WINPR_API HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T d WINPR_API HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); -WINPR_API VOID ExitThread(DWORD dwExitCode); +DECLSPEC_NORETURN WINPR_API VOID ExitThread(DWORD dwExitCode); +WINPR_API BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode); WINPR_API HANDLE _GetCurrentThread(VOID); WINPR_API DWORD GetCurrentThreadId(VOID); diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index ed15b463f..2e7869597 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -64,6 +64,9 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) if (status != 0) fprintf(stderr, "WaitForSingleObject: pthread_join failure: %d\n", status); + + if (thread_status) + thread->dwExitCode = ((DWORD*) thread_status); } else if (Type == HANDLE_TYPE_MUTEX) { diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index 72290404a..c2fe14a4c 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -128,6 +128,22 @@ VOID ExitThread(DWORD dwExitCode) pthread_exit((void*) dwExitCode); } +BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode) +{ + ULONG Type; + PVOID Object; + WINPR_THREAD* thread; + + if (!winpr_Handle_GetInfo(hThread, &Type, &Object)) + return FALSE; + + thread = (WINPR_THREAD*) Object; + + *lpExitCode = thread->dwExitCode; + + return TRUE; +} + HANDLE _GetCurrentThread(VOID) { return NULL; diff --git a/winpr/libwinpr/thread/thread.h b/winpr/libwinpr/thread/thread.h index a9b3b2f8d..263512fee 100644 --- a/winpr/libwinpr/thread/thread.h +++ b/winpr/libwinpr/thread/thread.h @@ -31,6 +31,7 @@ typedef void *(*pthread_start_routine)(void*); struct winpr_thread { BOOL started; + DWORD dwExitCode; pthread_t thread; SIZE_T dwStackSize; LPVOID lpParameter;