Merge branch 'master' of git://github.com/awakecoding/FreeRDP
This commit is contained in:
commit
184ee149f6
@ -312,6 +312,11 @@ if(NOT IOS AND NOT ANDROID)
|
|||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
|
check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT)
|
||||||
|
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
|
|
||||||
|
|
||||||
if(UNIX OR CYGWIN)
|
if(UNIX OR CYGWIN)
|
||||||
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
||||||
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
|
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
|
||||||
|
@ -54,6 +54,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
|||||||
{ "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" },
|
{ "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" },
|
||||||
{ "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
|
{ "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
|
||||||
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
|
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
|
||||||
|
{ "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Client Hostname to send to server" },
|
||||||
{ "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
|
{ "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
|
||||||
{ "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
|
{ "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
|
||||||
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
|
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
|
||||||
@ -1244,6 +1245,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||||||
settings->RestrictedAdminModeRequired = TRUE;
|
settings->RestrictedAdminModeRequired = TRUE;
|
||||||
settings->PasswordHash = _strdup(arg->Value);
|
settings->PasswordHash = _strdup(arg->Value);
|
||||||
}
|
}
|
||||||
|
CommandLineSwitchCase(arg, "client-hostname")
|
||||||
|
{
|
||||||
|
settings->ClientHostname = _strdup(arg->Value);
|
||||||
|
}
|
||||||
CommandLineSwitchCase(arg, "kbd")
|
CommandLineSwitchCase(arg, "kbd")
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
@ -500,6 +500,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
|
|||||||
CommandLineSwitchCase(arg, "n")
|
CommandLineSwitchCase(arg, "n")
|
||||||
{
|
{
|
||||||
settings->ClientHostname = _strdup(arg->Value);
|
settings->ClientHostname = _strdup(arg->Value);
|
||||||
|
fprintf(stderr, "-n -> /client-hostname:%s\n", arg->Value);
|
||||||
}
|
}
|
||||||
CommandLineSwitchCase(arg, "o")
|
CommandLineSwitchCase(arg, "o")
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#import "TSXAdditions.h"
|
#import "TSXAdditions.h"
|
||||||
|
|
||||||
#import <freerdp/input.h>
|
#import <freerdp/input.h>
|
||||||
|
#import <freerdp/version.h>
|
||||||
#import "config.h"
|
#import "config.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -279,10 +279,10 @@ static UIFont *buttonFont = nil;
|
|||||||
button.frame = CGRectMake(xOffset, _height, width, kAlertButtonHeight);
|
button.frame = CGRectMake(xOffset, _height, width, kAlertButtonHeight);
|
||||||
button.titleLabel.font = buttonFont;
|
button.titleLabel.font = buttonFont;
|
||||||
if (IOS_LESS_THAN_6) {
|
if (IOS_LESS_THAN_6) {
|
||||||
#pragma clan diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
button.titleLabel.minimumFontSize = 10;
|
button.titleLabel.minimumFontSize = 10;
|
||||||
#pragma clan diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
button.titleLabel.adjustsFontSizeToFitWidth = YES;
|
button.titleLabel.adjustsFontSizeToFitWidth = YES;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#cmakedefine HAVE_TIMERFD_H
|
#cmakedefine HAVE_TIMERFD_H
|
||||||
#cmakedefine HAVE_TM_GMTOFF
|
#cmakedefine HAVE_TM_GMTOFF
|
||||||
#cmakedefine HAVE_AIO_H
|
#cmakedefine HAVE_AIO_H
|
||||||
|
#cmakedefine HAVE_PTHREAD_GNU_EXT
|
||||||
|
|
||||||
|
|
||||||
/* Options */
|
/* Options */
|
||||||
|
@ -818,6 +818,54 @@ BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id)
|
|||||||
return (status < 0) ? FALSE : TRUE;
|
return (status < 0) ? FALSE : TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive MCS Disconnect Provider Ultimatum PDU.\n
|
||||||
|
* @param mcs mcs module
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason)
|
||||||
|
{
|
||||||
|
BYTE b1, b2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* http://msdn.microsoft.com/en-us/library/cc240872.aspx:
|
||||||
|
*
|
||||||
|
* PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
|
||||||
|
* 21 80
|
||||||
|
*
|
||||||
|
* 0x21:
|
||||||
|
* 0 - --\
|
||||||
|
* 0 - |
|
||||||
|
* 1 - | CHOICE: From DomainMCSPDU select disconnectProviderUltimatum (8)
|
||||||
|
* 0 - | of type DisconnectProviderUltimatum
|
||||||
|
* 0 - |
|
||||||
|
* 0 - --/
|
||||||
|
* 0 - --\
|
||||||
|
* 1 - |
|
||||||
|
* | DisconnectProviderUltimatum::reason = rn-user-requested (3)
|
||||||
|
* 0x80: |
|
||||||
|
* 1 - --/
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
* 0 - padding
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Stream_Rewind_UINT8(s);
|
||||||
|
Stream_Read_UINT8(s, b1);
|
||||||
|
Stream_Read_UINT8(s, b2);
|
||||||
|
|
||||||
|
*reason = ((b1 & 0x01) << 1) | (b2 >> 7);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send MCS Disconnect Provider Ultimatum PDU.\n
|
* Send MCS Disconnect Provider Ultimatum PDU.\n
|
||||||
* @param mcs mcs module
|
* @param mcs mcs module
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef __MCS_H
|
#ifndef __MCS_H
|
||||||
#define __MCS_H
|
#define __MCS_H
|
||||||
|
|
||||||
|
typedef struct rdp_mcs rdpMcs;
|
||||||
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
#include <freerdp/crypto/ber.h>
|
#include <freerdp/crypto/ber.h>
|
||||||
@ -52,6 +54,15 @@ enum MCS_Result
|
|||||||
MCS_Result_enum_length = 16
|
MCS_Result_enum_length = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MCS_Reason
|
||||||
|
{
|
||||||
|
MCS_Reason_domain_disconnected = 0,
|
||||||
|
MCS_Reason_provider_initiated = 1,
|
||||||
|
MCS_Reason_token_purged = 2,
|
||||||
|
MCS_Reason_user_requested = 3,
|
||||||
|
MCS_Reason_channel_purged = 4
|
||||||
|
};
|
||||||
|
|
||||||
enum DomainMCSPDU
|
enum DomainMCSPDU
|
||||||
{
|
{
|
||||||
DomainMCSPDU_PlumbDomainIndication = 0,
|
DomainMCSPDU_PlumbDomainIndication = 0,
|
||||||
@ -115,7 +126,7 @@ typedef struct
|
|||||||
struct rdp_mcs
|
struct rdp_mcs
|
||||||
{
|
{
|
||||||
UINT16 user_id;
|
UINT16 user_id;
|
||||||
struct rdp_transport* transport;
|
rdpTransport* transport;
|
||||||
DomainParameters domainParameters;
|
DomainParameters domainParameters;
|
||||||
DomainParameters targetParameters;
|
DomainParameters targetParameters;
|
||||||
DomainParameters minimumParameters;
|
DomainParameters minimumParameters;
|
||||||
@ -124,7 +135,6 @@ struct rdp_mcs
|
|||||||
BOOL user_channel_joined;
|
BOOL user_channel_joined;
|
||||||
BOOL global_channel_joined;
|
BOOL global_channel_joined;
|
||||||
};
|
};
|
||||||
typedef struct rdp_mcs rdpMcs;
|
|
||||||
|
|
||||||
#define MCS_SEND_DATA_HEADER_MAX_LENGTH 8
|
#define MCS_SEND_DATA_HEADER_MAX_LENGTH 8
|
||||||
|
|
||||||
@ -148,6 +158,7 @@ BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
|||||||
BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id);
|
BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channel_id);
|
||||||
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channel_id);
|
||||||
BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id);
|
BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channel_id);
|
||||||
|
BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason);
|
||||||
BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
|
BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
|
||||||
BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length);
|
BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length);
|
||||||
void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length, BYTE options);
|
void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length, BYTE options);
|
||||||
|
@ -229,6 +229,25 @@ wStream* rdp_data_pdu_init(rdpRdp* rdp)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
|
||||||
|
{
|
||||||
|
rdp->errorInfo = errorInfo;
|
||||||
|
|
||||||
|
if (rdp->errorInfo != ERRINFO_SUCCESS)
|
||||||
|
{
|
||||||
|
ErrorInfoEventArgs e;
|
||||||
|
rdpContext* context = rdp->instance->context;
|
||||||
|
|
||||||
|
rdp_print_errinfo(rdp->errorInfo);
|
||||||
|
|
||||||
|
EventArgsInit(&e, "freerdp");
|
||||||
|
e.code = rdp->errorInfo;
|
||||||
|
PubSub_OnErrorInfo(context->pubSub, context, &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an RDP packet header.\n
|
* Read an RDP packet header.\n
|
||||||
* @param rdp rdp module
|
* @param rdp rdp module
|
||||||
@ -256,12 +275,30 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||||||
|
|
||||||
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
|
if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
|
||||||
{
|
{
|
||||||
BYTE reason;
|
int reason = 0;
|
||||||
TerminateEventArgs e;
|
TerminateEventArgs e;
|
||||||
rdpContext* context = rdp->instance->context;
|
rdpContext* context = rdp->instance->context;
|
||||||
|
|
||||||
(void) per_read_enumerated(s, &reason, 0);
|
if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
|
||||||
DEBUG_RDP("DisconnectProviderUltimatum from server, reason code 0x%02x\n", reason);
|
return FALSE;
|
||||||
|
|
||||||
|
if (rdp->errorInfo == ERRINFO_SUCCESS)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Some servers like Windows Server 2008 R2 do not send the error info pdu
|
||||||
|
* when the user logs off like they should. Map DisconnectProviderUltimatum
|
||||||
|
* to a ERRINFO_LOGOFF_BY_USER when the errinfo code is ERRINFO_SUCCESS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason == MCS_Reason_provider_initiated)
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||||
|
else if (reason == MCS_Reason_user_requested)
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_LOGOFF_BY_USER);
|
||||||
|
else
|
||||||
|
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "DisconnectProviderUltimatum: reason: %d\n", reason);
|
||||||
|
|
||||||
rdp->disconnect = TRUE;
|
rdp->disconnect = TRUE;
|
||||||
|
|
||||||
@ -503,22 +540,14 @@ BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
|
|||||||
|
|
||||||
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
|
BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
|
||||||
{
|
{
|
||||||
|
UINT32 errorInfo;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 4)
|
if (Stream_GetRemainingLength(s) < 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
Stream_Read_UINT32(s, rdp->errorInfo); /* errorInfo (4 bytes) */
|
Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */
|
||||||
|
|
||||||
if (rdp->errorInfo != ERRINFO_SUCCESS)
|
rdp_set_error_info(rdp, errorInfo);
|
||||||
{
|
|
||||||
ErrorInfoEventArgs e;
|
|
||||||
rdpContext* context = rdp->instance->context;
|
|
||||||
|
|
||||||
rdp_print_errinfo(rdp->errorInfo);
|
|
||||||
|
|
||||||
EventArgsInit(&e, "freerdp");
|
|
||||||
e.code = rdp->errorInfo;
|
|
||||||
PubSub_OnErrorInfo(context->pubSub, context, &e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,9 @@ BOOL transport_disconnect(rdpTransport* transport)
|
|||||||
{
|
{
|
||||||
BOOL status = TRUE;
|
BOOL status = TRUE;
|
||||||
|
|
||||||
|
if (!transport)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||||
status &= tls_disconnect(transport->TlsIn);
|
status &= tls_disconnect(transport->TlsIn);
|
||||||
|
|
||||||
|
@ -360,6 +360,9 @@ BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
|
|||||||
|
|
||||||
BOOL tls_disconnect(rdpTls* tls)
|
BOOL tls_disconnect(rdpTls* tls)
|
||||||
{
|
{
|
||||||
|
if (!tls)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (tls->ssl)
|
if (tls->ssl)
|
||||||
SSL_shutdown(tls->ssl);
|
SSL_shutdown(tls->ssl);
|
||||||
|
|
||||||
|
@ -18,13 +18,8 @@
|
|||||||
set(MODULE_NAME "winpr-synch")
|
set(MODULE_NAME "winpr-synch")
|
||||||
set(MODULE_PREFIX "WINPR_SYNCH")
|
set(MODULE_PREFIX "WINPR_SYNCH")
|
||||||
|
|
||||||
INCLUDE (CheckLibraryExists)
|
|
||||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
|
||||||
check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT)
|
|
||||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
|
||||||
|
|
||||||
if(HAVE_PTHREAD_GNU_EXT)
|
if(HAVE_PTHREAD_GNU_EXT)
|
||||||
add_definitions(-D_GNU_SOURCE -DHAVE_PTHREAD_GNU_EXT)
|
add_definitions(-D_GNU_SOURCE)
|
||||||
endif(HAVE_PTHREAD_GNU_EXT)
|
endif(HAVE_PTHREAD_GNU_EXT)
|
||||||
|
|
||||||
include_directories(../thread)
|
include_directories(../thread)
|
||||||
|
@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS
|
|||||||
TestSynchMutex.c
|
TestSynchMutex.c
|
||||||
TestSynchCritical.c
|
TestSynchCritical.c
|
||||||
TestSynchSemaphore.c
|
TestSynchSemaphore.c
|
||||||
|
TestSynchThread.c
|
||||||
TestSynchWaitableTimer.c)
|
TestSynchWaitableTimer.c)
|
||||||
|
|
||||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||||
|
@ -4,16 +4,48 @@
|
|||||||
|
|
||||||
int TestSynchMutex(int argc, char* argv[])
|
int TestSynchMutex(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
DWORD rc;
|
||||||
HANDLE mutex;
|
HANDLE mutex;
|
||||||
|
|
||||||
mutex = CreateMutex(NULL, FALSE, NULL);
|
mutex = CreateMutex(NULL, FALSE, NULL);
|
||||||
|
|
||||||
if (!mutex)
|
if (!mutex)
|
||||||
{
|
{
|
||||||
printf("CreateMutex failure\n");
|
printf("CreateMutex failure\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lock the mutex */
|
||||||
|
rc = WaitForSingleObject(mutex, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 != rc)
|
||||||
|
{
|
||||||
|
printf("WaitForSingleObject on mutex failed with %d\n", rc);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TryLock should now fail. */
|
||||||
|
rc = WaitForSingleObject(mutex, 0);
|
||||||
|
if (WAIT_TIMEOUT != rc)
|
||||||
|
{
|
||||||
|
printf("Timed WaitForSingleObject on locked mutex failed with %d\n", rc);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the mutex */
|
||||||
|
rc = ReleaseMutex(mutex);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
printf("ReleaseMutex failed.\n");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TryLock should now succeed. */
|
||||||
|
rc = WaitForSingleObject(mutex, 0);
|
||||||
|
if (WAIT_OBJECT_0 != rc)
|
||||||
|
{
|
||||||
|
printf("Timed WaitForSingleObject on free mutex failed with %d\n", rc);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(mutex);
|
CloseHandle(mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
55
winpr/libwinpr/synch/test/TestSynchThread.c
Normal file
55
winpr/libwinpr/synch/test/TestSynchThread.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/synch.h>
|
||||||
|
#include <winpr/thread.h>
|
||||||
|
|
||||||
|
static void *test_thread(void *arg)
|
||||||
|
{
|
||||||
|
Sleep(1000);
|
||||||
|
|
||||||
|
ExitThread(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestSynchThread(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
DWORD rc;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_thread,
|
||||||
|
NULL, 0, NULL);
|
||||||
|
if (!thread)
|
||||||
|
{
|
||||||
|
printf("CreateThread failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TryJoin should now fail. */
|
||||||
|
rc = WaitForSingleObject(thread, 0);
|
||||||
|
if (WAIT_TIMEOUT != rc)
|
||||||
|
{
|
||||||
|
printf("Timed WaitForSingleObject on running thread failed with %d\n", rc);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Join the thread */
|
||||||
|
rc = WaitForSingleObject(thread, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 != rc)
|
||||||
|
{
|
||||||
|
printf("WaitForSingleObject on thread failed with %d\n", rc);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TimedJoin should now succeed. */
|
||||||
|
rc = WaitForSingleObject(thread, 0);
|
||||||
|
if (WAIT_OBJECT_0 != rc)
|
||||||
|
{
|
||||||
|
printf("Timed WaitForSingleObject on dead thread failed with %d\n", rc);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -86,10 +86,20 @@ int clock_gettime(int clk_id, struct timespec *t)
|
|||||||
*/
|
*/
|
||||||
#if !defined(HAVE_PTHREAD_GNU_EXT)
|
#if !defined(HAVE_PTHREAD_GNU_EXT)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
static long long ts_difftime(struct timespec *o,
|
||||||
|
struct timespec *n)
|
||||||
|
{
|
||||||
|
long long old = o->tv_sec * 1000000000LL + o->tv_nsec;
|
||||||
|
long long new = n->tv_sec * 1000000000LL + n->tv_nsec;
|
||||||
|
|
||||||
|
return new - old;
|
||||||
|
}
|
||||||
|
|
||||||
static int pthread_timedjoin_np(pthread_t td, void **res,
|
static int pthread_timedjoin_np(pthread_t td, void **res,
|
||||||
struct timespec *timeout)
|
struct timespec *timeout)
|
||||||
{
|
{
|
||||||
struct timeval timenow;
|
struct timespec timenow;
|
||||||
struct timespec sleepytime;
|
struct timespec sleepytime;
|
||||||
/* This is just to avoid a completely busy wait */
|
/* This is just to avoid a completely busy wait */
|
||||||
sleepytime.tv_sec = 0;
|
sleepytime.tv_sec = 0;
|
||||||
@ -101,11 +111,10 @@ static int pthread_timedjoin_np(pthread_t td, void **res,
|
|||||||
return pthread_join(td, res);
|
return pthread_join(td, res);
|
||||||
|
|
||||||
nanosleep(&sleepytime, NULL);
|
nanosleep(&sleepytime, NULL);
|
||||||
|
|
||||||
gettimeofday(&timenow, NULL);
|
clock_gettime(CLOCK_MONOTONIC, &timenow);
|
||||||
|
|
||||||
if (timenow.tv_sec >= timeout->tv_sec &&
|
if (ts_difftime(timeout, &timenow) >= 0)
|
||||||
(timenow.tv_usec * 1000) >= timeout->tv_nsec)
|
|
||||||
{
|
{
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
}
|
}
|
||||||
@ -117,7 +126,7 @@ static int pthread_timedjoin_np(pthread_t td, void **res,
|
|||||||
|
|
||||||
static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout)
|
static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *timeout)
|
||||||
{
|
{
|
||||||
struct timeval timenow;
|
struct timespec timenow;
|
||||||
struct timespec sleepytime;
|
struct timespec sleepytime;
|
||||||
int retcode;
|
int retcode;
|
||||||
|
|
||||||
@ -127,10 +136,9 @@ static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec
|
|||||||
|
|
||||||
while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY)
|
while ((retcode = pthread_mutex_trylock (mutex)) == EBUSY)
|
||||||
{
|
{
|
||||||
gettimeofday (&timenow, NULL);
|
clock_gettime(CLOCK_MONOTONIC, &timenow);
|
||||||
|
|
||||||
if (timenow.tv_sec >= timeout->tv_sec &&
|
if (ts_difftime(timeout, &timenow) >= 0)
|
||||||
(timenow.tv_usec * 1000) >= timeout->tv_nsec)
|
|
||||||
{
|
{
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
}
|
}
|
||||||
@ -172,7 +180,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
|
|
||||||
if (thread->started)
|
if (thread->started)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
|
||||||
if (dwMilliseconds != INFINITE)
|
if (dwMilliseconds != INFINITE)
|
||||||
{
|
{
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
@ -182,7 +189,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
if (dwMilliseconds == 0)
|
if (dwMilliseconds == 0)
|
||||||
dwMilliseconds ++;
|
dwMilliseconds ++;
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &timeout);
|
clock_gettime(CLOCK_MONOTONIC, &timeout);
|
||||||
ts_add_ms(&timeout, dwMilliseconds);
|
ts_add_ms(&timeout, dwMilliseconds);
|
||||||
|
|
||||||
status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);
|
status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);
|
||||||
@ -191,7 +198,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
return WAIT_TIMEOUT;
|
return WAIT_TIMEOUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
status = pthread_join(thread->thread, &thread_status);
|
status = pthread_join(thread->thread, &thread_status);
|
||||||
|
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
@ -223,13 +229,12 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
|
|
||||||
mutex = (WINPR_MUTEX*) Object;
|
mutex = (WINPR_MUTEX*) Object;
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
if (dwMilliseconds != INFINITE)
|
if (dwMilliseconds != INFINITE)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &timeout);
|
clock_gettime(CLOCK_MONOTONIC, &timeout);
|
||||||
ts_add_ms(&timeout, dwMilliseconds);
|
ts_add_ms(&timeout, dwMilliseconds);
|
||||||
|
|
||||||
status = pthread_mutex_timedlock(&mutex->mutex, &timeout);
|
status = pthread_mutex_timedlock(&mutex->mutex, &timeout);
|
||||||
@ -238,7 +243,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
return WAIT_TIMEOUT;
|
return WAIT_TIMEOUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
pthread_mutex_lock(&mutex->mutex);
|
pthread_mutex_lock(&mutex->mutex);
|
||||||
}
|
}
|
||||||
else if (Type == HANDLE_TYPE_EVENT)
|
else if (Type == HANDLE_TYPE_EVENT)
|
||||||
|
Loading…
Reference in New Issue
Block a user