DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { ULONG Type; PVOID Object; if (!winpr_Handle_GetInfo(hHandle, &Type, &Object)) return WAIT_FAILED; if (Type == HANDLE_TYPE_THREAD) { int status = 0; WINPR_THREAD* thread; void* thread_status = NULL; thread = (WINPR_THREAD*) Object; if (thread->started) { if (dwMilliseconds != INFINITE) { #if HAVE_PTHREAD_GNU_EXT struct timespec timeout; clock_gettime(CLOCK_REALTIME, &timeout); ts_add_ms(&timeout, dwMilliseconds); status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout); #else fprintf(stderr, "[ERROR] %s: Thread timeouts not implemented.\n", __func__); assert(0); #endif } else status = pthread_join(thread->thread, &thread_status); if (status != 0) fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n", status, strerror(status)); if (thread_status) thread->dwExitCode = ((DWORD) (size_t) thread_status); } } else if (Type == HANDLE_TYPE_MUTEX) { WINPR_MUTEX* mutex; mutex = (WINPR_MUTEX*) Object; #if HAVE_PTHREAD_GNU_EXT if (dwMilliseconds != INFINITE) { struct timespec timeout; clock_gettime(CLOCK_REALTIME, &timeout); ts_add_ms(&timeout, dwMilliseconds); pthread_mutex_timedlock(&mutex->mutex, &timeout); } else #endif { pthread_mutex_lock(&mutex->mutex); } } else if (Type == HANDLE_TYPE_EVENT) { int status; fd_set rfds; WINPR_EVENT* event; struct timeval timeout; event = (WINPR_EVENT*) Object; FD_ZERO(&rfds); FD_SET(event->pipe_fd[0], &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_usec = dwMilliseconds * 1000; } status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout); if (status < 0) return WAIT_FAILED; if (status != 1) return WAIT_TIMEOUT; } else if (Type == HANDLE_TYPE_SEMAPHORE) { WINPR_SEMAPHORE* semaphore; semaphore = (WINPR_SEMAPHORE*) Object; #ifdef WINPR_PIPE_SEMAPHORE if (semaphore->pipe_fd[0] != -1) { int status; int length; fd_set rfds; struct timeval timeout; FD_ZERO(&rfds); FD_SET(semaphore->pipe_fd[0], &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_usec = dwMilliseconds * 1000; } status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); if (status < 0) return WAIT_FAILED; if (status != 1) return WAIT_TIMEOUT; length = read(semaphore->pipe_fd[0], &length, 1); if (length != 1) return WAIT_FAILED; } #else #if defined __APPLE__ semaphore_wait(*((winpr_sem_t*) semaphore->sem)); #else sem_wait((winpr_sem_t*) semaphore->sem); #endif #endif } else if (Type == HANDLE_TYPE_TIMER) { WINPR_TIMER* timer; timer = (WINPR_TIMER*) Object; #ifdef HAVE_EVENTFD_H if (timer->fd != -1) { int status; fd_set rfds; UINT64 expirations; struct timeval timeout; FD_ZERO(&rfds); FD_SET(timer->fd, &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_usec = dwMilliseconds * 1000; } status = select(timer->fd + 1, &rfds, 0, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); if (status < 0) return WAIT_FAILED; if (status != 1) return WAIT_TIMEOUT; status = read(timer->fd, (void*) &expirations, sizeof(UINT64)); if (status != 8) return WAIT_TIMEOUT; } else { return WAIT_FAILED; } #else return WAIT_FAILED; #endif } else if (Type == HANDLE_TYPE_NAMED_PIPE) { int status; fd_set rfds; struct timeval timeout; WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; FD_ZERO(&rfds); FD_SET(pipe->clientfd, &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_usec = dwMilliseconds * 1000; } status = select(pipe->clientfd + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout); if (status < 0) return WAIT_FAILED; if (status != 1) return WAIT_TIMEOUT; } else { fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type); } return WAIT_OBJECT_0; }
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { ULONG Type; PVOID Object; if (!winpr_Handle_GetInfo(hHandle, &Type, &Object)) { fprintf(stderr, "WaitForSingleObject failed: invalid hHandle.\n"); return WAIT_FAILED; } if (Type == HANDLE_TYPE_THREAD) { int status = 0; WINPR_THREAD* thread; void* thread_status = NULL; thread = (WINPR_THREAD*) Object; if (thread->started) { if (dwMilliseconds != INFINITE) { struct timespec timeout; /* pthread_timedjoin_np returns ETIMEDOUT in case the timeout is 0, * so set it to the smallest value to get a proper return value. */ if (dwMilliseconds == 0) dwMilliseconds ++; clock_gettime(CLOCK_MONOTONIC, &timeout); ts_add_ms(&timeout, dwMilliseconds); status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout); if (ETIMEDOUT == status) return WAIT_TIMEOUT; } else status = pthread_join(thread->thread, &thread_status); if (status != 0) { fprintf(stderr, "WaitForSingleObject: pthread_join failure: [%d] %s\n", status, strerror(status)); } if (thread_status) thread->dwExitCode = ((DWORD) (size_t) thread_status); } } else if (Type == HANDLE_TYPE_PROCESS) { WINPR_PROCESS* process; process = (WINPR_PROCESS*) Object; if (waitpid(process->pid, &(process->status), 0) != -1) { fprintf(stderr, "WaitForSingleObject: waitpid failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } process->dwExitCode = (DWORD) process->status; } else if (Type == HANDLE_TYPE_MUTEX) { WINPR_MUTEX* mutex; mutex = (WINPR_MUTEX*) Object; if (dwMilliseconds != INFINITE) { int status; struct timespec timeout; clock_gettime(CLOCK_MONOTONIC, &timeout); ts_add_ms(&timeout, dwMilliseconds); status = pthread_mutex_timedlock(&mutex->mutex, &timeout); if (ETIMEDOUT == status) return WAIT_TIMEOUT; } else { pthread_mutex_lock(&mutex->mutex); } } else if (Type == HANDLE_TYPE_EVENT) { int status; fd_set rfds; WINPR_EVENT* event; struct timeval timeout; event = (WINPR_EVENT*) Object; FD_ZERO(&rfds); FD_SET(event->pipe_fd[0], &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && (errno == EINTR)); if (status < 0) { fprintf(stderr, "WaitForSingleObject: event select() failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } if (status != 1) return WAIT_TIMEOUT; } else if (Type == HANDLE_TYPE_SEMAPHORE) { WINPR_SEMAPHORE* semaphore; semaphore = (WINPR_SEMAPHORE*) Object; #ifdef WINPR_PIPE_SEMAPHORE if (semaphore->pipe_fd[0] != -1) { int status; int length; fd_set rfds; struct timeval timeout; FD_ZERO(&rfds); FD_SET(semaphore->pipe_fd[0], &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && (errno == EINTR)); if (status < 0) { fprintf(stderr, "WaitForSingleObject: semaphore select() failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } if (status != 1) return WAIT_TIMEOUT; length = read(semaphore->pipe_fd[0], &length, 1); if (length != 1) { fprintf(stderr, "WaitForSingleObject: semaphore read failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } } #else #if defined __APPLE__ semaphore_wait(*((winpr_sem_t*) semaphore->sem)); #else sem_wait((winpr_sem_t*) semaphore->sem); #endif #endif } else if (Type == HANDLE_TYPE_TIMER) { WINPR_TIMER* timer; timer = (WINPR_TIMER*) Object; #ifdef HAVE_EVENTFD_H if (timer->fd != -1) { int status; fd_set rfds; UINT64 expirations; struct timeval timeout; FD_ZERO(&rfds); FD_SET(timer->fd, &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(timer->fd + 1, &rfds, 0, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && (errno == EINTR)); if (status < 0) { fprintf(stderr, "WaitForSingleObject: timer select() failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } if (status != 1) return WAIT_TIMEOUT; status = read(timer->fd, (void*) &expirations, sizeof(UINT64)); if (status != 8) { if (status == -1) { if (errno == ETIMEDOUT) return WAIT_TIMEOUT; fprintf(stderr, "WaitForSingleObject: timer read() failure [%d] %s\n", errno, strerror(errno)); } else { fprintf(stderr, "WaitForSingleObject: timer read() failure - incorrect number of bytes read"); } return WAIT_FAILED; } } else { fprintf(stderr, "WaitForSingleObject: invalid timer file descriptor\n"); return WAIT_FAILED; } #else fprintf(stderr, "WaitForSingleObject: file descriptors not supported\n"); return WAIT_FAILED; #endif } else if (Type == HANDLE_TYPE_NAMED_PIPE) { int fd; int status; fd_set rfds; struct timeval timeout; WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd; if (fd == -1) { fprintf(stderr, "WaitForSingleObject: invalid pipe file descriptor\n"); return WAIT_FAILED; } FD_ZERO(&rfds); FD_SET(fd, &rfds); ZeroMemory(&timeout, sizeof(timeout)); if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) { timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_usec = (dwMilliseconds % 1000) * 1000; } do { status = select(fd + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout); } while (status < 0 && (errno == EINTR)); if (status < 0) { fprintf(stderr, "WaitForSingleObject: named pipe select() failure [%d] %s\n", errno, strerror(errno)); return WAIT_FAILED; } if (status != 1) { return WAIT_TIMEOUT; } } else { fprintf(stderr, "WaitForSingleObject: unknown handle type %lu\n", Type); } return WAIT_OBJECT_0; }
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { ULONG Type; PVOID Object; if (!winpr_Handle_GetInfo(hHandle, &Type, &Object)) { WLog_ERR(TAG, "invalid hHandle."); return WAIT_FAILED; } if (Type == HANDLE_TYPE_PROCESS) { WINPR_PROCESS *process; process = (WINPR_PROCESS *) Object; if (waitpid(process->pid, &(process->status), 0) != -1) { WLog_ERR(TAG, "waitpid failure [%d] %s", errno, strerror(errno)); return WAIT_FAILED; } process->dwExitCode = (DWORD) process->status; return WAIT_OBJECT_0; } else if (Type == HANDLE_TYPE_MUTEX) { WINPR_MUTEX *mutex; mutex = (WINPR_MUTEX *) Object; if (dwMilliseconds != INFINITE) { int status; struct timespec timeout; clock_gettime(CLOCK_MONOTONIC, &timeout); ts_add_ms(&timeout, dwMilliseconds); status = pthread_mutex_timedlock(&mutex->mutex, &timeout); if (ETIMEDOUT == status) return WAIT_TIMEOUT; } else { pthread_mutex_lock(&mutex->mutex); } return WAIT_OBJECT_0; } else { int status; int fd = winpr_Handle_getFd(Object); if (fd < 0) return WAIT_FAILED; status = waitOnFd(fd, dwMilliseconds); if (status < 0) { WLog_ERR(TAG, "waitOnFd() failure [%d] %s", errno, strerror(errno)); return WAIT_FAILED; } if (status != 1) return WAIT_TIMEOUT; return winpr_Handle_cleanup(Object); } return WAIT_FAILED; }