22#include <winpr/config.h>
28#include <winpr/synch.h>
34#ifdef WINPR_HAVE_UNISTD_H
38#ifdef WINPR_HAVE_SYS_EVENTFD_H
39#include <sys/eventfd.h>
45#include "../handle/handle.h"
46#include "../pipe/pipe.h"
50#define TAG WINPR_TAG("synch.event")
52#if defined(WITH_DEBUG_EVENTS)
53static wArrayList* global_event_list = NULL;
55static void dump_event(WINPR_EVENT* event,
size_t index)
60 WLog_DBG(TAG,
"Event handle created still not closed! [%" PRIuz
", %p]", index, event);
61 msg = winpr_backtrace_symbols(event->create_stack, &used);
63 for (
size_t i = 2; i < used; i++)
64 WLog_DBG(TAG,
"[%" PRIdz
"]: %s", i, msg[i]);
70#ifdef WINPR_HAVE_SYS_EVENTFD_H
71#if !defined(WITH_EVENTFD_READ_WRITE)
72static int eventfd_read(
int fd, eventfd_t* value)
74 return (read(fd, value,
sizeof(*value)) ==
sizeof(*value)) ? 0 : -1;
77static int eventfd_write(
int fd, eventfd_t value)
79 return (write(fd, &value,
sizeof(value)) ==
sizeof(value)) ? 0 : -1;
84#ifndef WINPR_HAVE_SYS_EVENTFD_H
85static BOOL set_non_blocking_fd(
int fd)
88 flags = fcntl(fd, F_GETFL);
92 return fcntl(fd, F_SETFL, flags | O_NONBLOCK) >= 0;
96BOOL winpr_event_init(WINPR_EVENT_IMPL* event)
98#ifdef WINPR_HAVE_SYS_EVENTFD_H
100 event->fds[0] = eventfd(0, EFD_NONBLOCK);
102 return event->fds[0] >= 0;
104 if (pipe(event->fds) < 0)
107 if (!set_non_blocking_fd(event->fds[0]) || !set_non_blocking_fd(event->fds[1]))
113 winpr_event_uninit(event);
118void winpr_event_init_from_fd(WINPR_EVENT_IMPL* event,
int fd)
121#ifndef WINPR_HAVE_SYS_EVENTFD_H
126BOOL winpr_event_set(WINPR_EVENT_IMPL* event)
131#ifdef WINPR_HAVE_SYS_EVENTFD_H
133 ret = eventfd_write(event->fds[0], value);
135 ret = write(event->fds[1],
"-", 1);
137 }
while (ret < 0 && errno == EINTR);
142BOOL winpr_event_reset(WINPR_EVENT_IMPL* event)
149#ifdef WINPR_HAVE_SYS_EVENTFD_H
151 ret = eventfd_read(event->fds[0], &value);
154 ret = read(event->fds[0], &value, 1);
156 }
while (ret < 0 && errno == EINTR);
159 return (errno == EAGAIN);
162void winpr_event_uninit(WINPR_EVENT_IMPL* event)
164 if (event->fds[0] >= 0)
166 close(event->fds[0]);
170 if (event->fds[1] >= 0)
172 close(event->fds[1]);
177static BOOL EventCloseHandle(HANDLE handle);
179static BOOL EventIsHandled(HANDLE handle)
181 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_EVENT, FALSE);
184static int EventGetFd(HANDLE handle)
186 WINPR_EVENT*
event = (WINPR_EVENT*)handle;
188 if (!EventIsHandled(handle))
191 return event->impl.fds[0];
194static BOOL EventCloseHandle_(WINPR_EVENT* event)
199 if (event->bAttached)
202 event->impl.fds[0] = -1;
205 winpr_event_uninit(&event->impl);
207#if defined(WITH_DEBUG_EVENTS)
208 if (global_event_list)
210 ArrayList_Remove(global_event_list, event);
211 if (ArrayList_Count(global_event_list) < 1)
213 ArrayList_Free(global_event_list);
214 global_event_list = NULL;
218 winpr_backtrace_free(event->create_stack);
225static BOOL EventCloseHandle(HANDLE handle)
227 WINPR_EVENT*
event = (WINPR_EVENT*)handle;
229 if (!EventIsHandled(handle))
232 return EventCloseHandle_(event);
257HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
260 HANDLE handle = NULL;
265 name = ConvertWCharToUtf8Alloc(lpName, NULL);
270 handle = CreateEventA(lpEventAttributes, bManualReset, bInitialState, name);
275HANDLE CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
278 WINPR_EVENT*
event = (WINPR_EVENT*)calloc(1,
sizeof(WINPR_EVENT));
280 if (lpEventAttributes)
281 WLog_WARN(TAG,
"[%s] does not support lpEventAttributes", lpName);
287 event->name = strdup(lpName);
289 event->impl.fds[0] = -1;
290 event->impl.fds[1] = -1;
291 event->bAttached = FALSE;
292 event->bManualReset = bManualReset;
293 event->common.ops = &ops;
294 WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, FD_READ);
296 if (!event->bManualReset)
297 WLog_ERR(TAG,
"auto-reset events not yet implemented");
299 if (!winpr_event_init(&event->impl))
304 if (!SetEvent(event))
308#if defined(WITH_DEBUG_EVENTS)
309 event->create_stack = winpr_backtrace(20);
310 if (!global_event_list)
311 global_event_list = ArrayList_New(TRUE);
313 if (global_event_list)
314 ArrayList_Append(global_event_list, event);
316 return (HANDLE)event;
318 EventCloseHandle_(event);
322HANDLE CreateEventExW(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCWSTR lpName, DWORD dwFlags,
323 DWORD dwDesiredAccess)
325 BOOL initial = FALSE;
328 if (dwFlags & CREATE_EVENT_INITIAL_SET)
331 if (dwFlags & CREATE_EVENT_MANUAL_RESET)
334 if (dwDesiredAccess != 0)
336 char name[MAX_PATH] = { 0 };
337 ConvertWCharToUtf8(lpName, name,
sizeof(name) - 1);
338 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, name, dwDesiredAccess);
341 return CreateEventW(lpEventAttributes, manual, initial, lpName);
344HANDLE CreateEventExA(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName, DWORD dwFlags,
345 DWORD dwDesiredAccess)
347 BOOL initial = FALSE;
350 if (dwFlags & CREATE_EVENT_INITIAL_SET)
353 if (dwFlags & CREATE_EVENT_MANUAL_RESET)
356 if (dwDesiredAccess != 0)
357 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
360 return CreateEventA(lpEventAttributes, manual, initial, lpName);
363HANDLE OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
366 WINPR_UNUSED(dwDesiredAccess);
367 WINPR_UNUSED(bInheritHandle);
368 WINPR_UNUSED(lpName);
369 WLog_ERR(TAG,
"not implemented");
373HANDLE OpenEventA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
376 WINPR_UNUSED(dwDesiredAccess);
377 WINPR_UNUSED(bInheritHandle);
378 WINPR_UNUSED(lpName);
379 WLog_ERR(TAG,
"not implemented");
383BOOL SetEvent(HANDLE hEvent)
387 WINPR_EVENT*
event = NULL;
389 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
391 WLog_ERR(TAG,
"SetEvent: hEvent is not an event");
392 SetLastError(ERROR_INVALID_PARAMETER);
396 event = (WINPR_EVENT*)Object;
397 return winpr_event_set(&event->impl);
400BOOL ResetEvent(HANDLE hEvent)
404 WINPR_EVENT*
event = NULL;
406 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
408 WLog_ERR(TAG,
"ResetEvent: hEvent is not an event");
409 SetLastError(ERROR_INVALID_PARAMETER);
413 event = (WINPR_EVENT*)Object;
414 return winpr_event_reset(&event->impl);
419HANDLE CreateFileDescriptorEventW(WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpEventAttributes,
420 BOOL bManualReset, WINPR_ATTR_UNUSED BOOL bInitialState,
421 int FileDescriptor, ULONG mode)
424 WINPR_EVENT*
event = NULL;
425 HANDLE handle = NULL;
426 event = (WINPR_EVENT*)calloc(1,
sizeof(WINPR_EVENT));
430 event->impl.fds[0] = -1;
431 event->impl.fds[1] = -1;
432 event->bAttached = TRUE;
433 event->bManualReset = bManualReset;
434 winpr_event_init_from_fd(&event->impl, FileDescriptor);
435 event->common.ops = &ops;
436 WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, mode);
437 handle = (HANDLE)event;
446HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
447 BOOL bInitialState,
int FileDescriptor, ULONG mode)
449 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
450 FileDescriptor, mode);
456HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
457 BOOL bInitialState,
void* pObject)
460 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
461 (
int)(ULONG_PTR)pObject, WINPR_FD_READ);
463 HANDLE hEvent = NULL;
464 DuplicateHandle(GetCurrentProcess(), pObject, GetCurrentProcess(), &hEvent, 0, FALSE,
465 DUPLICATE_SAME_ACCESS);
475int GetEventFileDescriptor(HANDLE hEvent)
478 return winpr_Handle_getFd(hEvent);
489int SetEventFileDescriptor(HANDLE hEvent,
int FileDescriptor, ULONG mode)
494 WINPR_EVENT*
event = NULL;
496 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
498 WLog_ERR(TAG,
"SetEventFileDescriptor: hEvent is not an event");
499 SetLastError(ERROR_INVALID_PARAMETER);
503 event = (WINPR_EVENT*)Object;
505 if (!event->bAttached && event->impl.fds[0] >= 0 && event->impl.fds[0] != FileDescriptor)
506 close(event->impl.fds[0]);
508 event->bAttached = TRUE;
509 event->common.Mode = mode;
510 event->impl.fds[0] = FileDescriptor;
527void* GetEventWaitObject(HANDLE hEvent)
532 fd = GetEventFileDescriptor(hEvent);
533 obj = ((
void*)(
long)fd);
539#if defined(WITH_DEBUG_EVENTS)
543#include <sys/resource.h>
545static BOOL dump_handle_list(
void* data,
size_t index, va_list ap)
547 WINPR_EVENT*
event = data;
548 dump_event(event, index);
552void DumpEventHandles_(
const char* fkt,
const char* file,
size_t line)
554 struct rlimit r = { 0 };
555 int rc = getrlimit(RLIMIT_NOFILE, &r);
559 for (rlim_t x = 0; x < r.rlim_cur; x++)
561 int flags = fcntl(x, F_GETFD);
565 WLog_INFO(TAG,
"------- limits [%d/%d] open files %" PRIuz, r.rlim_cur, r.rlim_max, count);
567 WLog_DBG(TAG,
"--------- Start dump [%s %s:%" PRIuz
"]", fkt, file, line);
568 if (global_event_list)
570 ArrayList_Lock(global_event_list);
571 ArrayList_ForEach(global_event_list, dump_handle_list);
572 ArrayList_Unlock(global_event_list);
574 WLog_DBG(TAG,
"--------- End dump [%s %s:%" PRIuz
"]", fkt, file, line);