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)
53 static wArrayList* global_event_list = NULL;
55 static void dump_event(WINPR_EVENT* event,
size_t index)
60 void* stack = winpr_backtrace(20);
61 WLog_DBG(TAG,
"Called from:");
62 msg = winpr_backtrace_symbols(stack, &used);
64 for (
size_t i = 0; i < used; i++)
65 WLog_DBG(TAG,
"[%" PRIdz
"]: %s", i, msg[i]);
68 winpr_backtrace_free(stack);
70 WLog_DBG(TAG,
"Event handle created still not closed! [%" PRIuz
", %p]", index, event);
71 msg = winpr_backtrace_symbols(event->create_stack, &used);
73 for (
size_t i = 2; i < used; i++)
74 WLog_DBG(TAG,
"[%" PRIdz
"]: %s", i, msg[i]);
80 #ifdef WINPR_HAVE_SYS_EVENTFD_H
81 #if !defined(WITH_EVENTFD_READ_WRITE)
82 static int eventfd_read(
int fd, eventfd_t* value)
84 return (read(fd, value,
sizeof(*value)) ==
sizeof(*value)) ? 0 : -1;
87 static int eventfd_write(
int fd, eventfd_t value)
89 return (write(fd, &value,
sizeof(value)) ==
sizeof(value)) ? 0 : -1;
94 #ifndef WINPR_HAVE_SYS_EVENTFD_H
95 static BOOL set_non_blocking_fd(
int fd)
98 flags = fcntl(fd, F_GETFL);
102 return fcntl(fd, F_SETFL, flags | O_NONBLOCK) >= 0;
106 BOOL winpr_event_init(WINPR_EVENT_IMPL* event)
108 #ifdef WINPR_HAVE_SYS_EVENTFD_H
110 event->fds[0] = eventfd(0, EFD_NONBLOCK);
112 return event->fds[0] >= 0;
114 if (pipe(event->fds) < 0)
117 if (!set_non_blocking_fd(event->fds[0]) || !set_non_blocking_fd(event->fds[1]))
123 winpr_event_uninit(event);
128 void winpr_event_init_from_fd(WINPR_EVENT_IMPL* event,
int fd)
131 #ifndef WINPR_HAVE_SYS_EVENTFD_H
136 BOOL winpr_event_set(WINPR_EVENT_IMPL* event)
141 #ifdef WINPR_HAVE_SYS_EVENTFD_H
143 ret = eventfd_write(event->fds[0], value);
145 ret = write(event->fds[1],
"-", 1);
147 }
while (ret < 0 && errno == EINTR);
152 BOOL winpr_event_reset(WINPR_EVENT_IMPL* event)
159 #ifdef WINPR_HAVE_SYS_EVENTFD_H
161 ret = eventfd_read(event->fds[0], &value);
164 ret = read(event->fds[0], &value, 1);
166 }
while (ret < 0 && errno == EINTR);
169 return (errno == EAGAIN);
172 void winpr_event_uninit(WINPR_EVENT_IMPL* event)
174 if (event->fds[0] != -1)
176 close(event->fds[0]);
180 if (event->fds[1] != -1)
182 close(event->fds[1]);
187 static BOOL EventCloseHandle(HANDLE handle);
189 static BOOL EventIsHandled(HANDLE handle)
191 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_EVENT, FALSE);
194 static int EventGetFd(HANDLE handle)
196 WINPR_EVENT*
event = (WINPR_EVENT*)handle;
198 if (!EventIsHandled(handle))
201 return event->impl.fds[0];
204 static BOOL EventCloseHandle_(WINPR_EVENT* event)
209 if (event->bAttached)
212 event->impl.fds[0] = -1;
215 winpr_event_uninit(&event->impl);
217 #if defined(WITH_DEBUG_EVENTS)
218 if (global_event_list)
220 ArrayList_Remove(global_event_list, event);
221 if (ArrayList_Count(global_event_list) < 1)
223 ArrayList_Free(global_event_list);
224 global_event_list = NULL;
228 winpr_backtrace_free(event->create_stack);
235 static BOOL EventCloseHandle(HANDLE handle)
237 WINPR_EVENT*
event = (WINPR_EVENT*)handle;
239 if (!EventIsHandled(handle))
242 return EventCloseHandle_(event);
267 HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
270 HANDLE handle = NULL;
275 name = ConvertWCharToUtf8Alloc(lpName, NULL);
280 handle = CreateEventA(lpEventAttributes, bManualReset, bInitialState, name);
285 HANDLE CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState,
288 WINPR_EVENT*
event = (WINPR_EVENT*)calloc(1,
sizeof(WINPR_EVENT));
290 if (lpEventAttributes)
291 WLog_WARN(TAG,
"[%s] does not support lpEventAttributes", lpName);
297 event->name = strdup(lpName);
299 event->impl.fds[0] = -1;
300 event->impl.fds[1] = -1;
301 event->bAttached = FALSE;
302 event->bManualReset = bManualReset;
303 event->common.ops = &ops;
304 WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, FD_READ);
306 if (!event->bManualReset)
307 WLog_ERR(TAG,
"auto-reset events not yet implemented");
309 if (!winpr_event_init(&event->impl))
314 if (!SetEvent(event))
318 #if defined(WITH_DEBUG_EVENTS)
319 event->create_stack = winpr_backtrace(20);
320 if (!global_event_list)
321 global_event_list = ArrayList_New(TRUE);
323 if (global_event_list)
324 ArrayList_Append(global_event_list, event);
326 return (HANDLE)event;
328 EventCloseHandle_(event);
332 HANDLE CreateEventExW(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCWSTR lpName, DWORD dwFlags,
333 DWORD dwDesiredAccess)
335 BOOL initial = FALSE;
338 if (dwFlags & CREATE_EVENT_INITIAL_SET)
341 if (dwFlags & CREATE_EVENT_MANUAL_RESET)
344 if (dwDesiredAccess != 0)
345 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
348 return CreateEventW(lpEventAttributes, manual, initial, lpName);
351 HANDLE CreateEventExA(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName, DWORD dwFlags,
352 DWORD dwDesiredAccess)
354 BOOL initial = FALSE;
357 if (dwFlags & CREATE_EVENT_INITIAL_SET)
360 if (dwFlags & CREATE_EVENT_MANUAL_RESET)
363 if (dwDesiredAccess != 0)
364 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
367 return CreateEventA(lpEventAttributes, manual, initial, lpName);
370 HANDLE OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
373 WINPR_UNUSED(dwDesiredAccess);
374 WINPR_UNUSED(bInheritHandle);
375 WINPR_UNUSED(lpName);
376 WLog_ERR(TAG,
"not implemented");
380 HANDLE OpenEventA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
383 WINPR_UNUSED(dwDesiredAccess);
384 WINPR_UNUSED(bInheritHandle);
385 WINPR_UNUSED(lpName);
386 WLog_ERR(TAG,
"not implemented");
390 BOOL SetEvent(HANDLE hEvent)
394 WINPR_EVENT*
event = NULL;
396 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
398 WLog_ERR(TAG,
"SetEvent: hEvent is not an event");
399 SetLastError(ERROR_INVALID_PARAMETER);
403 event = (WINPR_EVENT*)Object;
404 return winpr_event_set(&event->impl);
407 BOOL ResetEvent(HANDLE hEvent)
411 WINPR_EVENT*
event = NULL;
413 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
415 WLog_ERR(TAG,
"ResetEvent: hEvent is not an event");
416 SetLastError(ERROR_INVALID_PARAMETER);
420 event = (WINPR_EVENT*)Object;
421 return winpr_event_reset(&event->impl);
426 HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
427 BOOL bInitialState,
int FileDescriptor, ULONG mode)
430 WINPR_EVENT*
event = NULL;
431 HANDLE handle = NULL;
432 event = (WINPR_EVENT*)calloc(1,
sizeof(WINPR_EVENT));
436 event->impl.fds[0] = -1;
437 event->impl.fds[1] = -1;
438 event->bAttached = TRUE;
439 event->bManualReset = bManualReset;
440 winpr_event_init_from_fd(&event->impl, FileDescriptor);
441 event->common.ops = &ops;
442 WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, mode);
443 handle = (HANDLE)event;
452 HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
453 BOOL bInitialState,
int FileDescriptor, ULONG mode)
455 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
456 FileDescriptor, mode);
462 HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
463 BOOL bInitialState,
void* pObject)
466 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
467 (
int)(ULONG_PTR)pObject, WINPR_FD_READ);
469 HANDLE hEvent = NULL;
470 DuplicateHandle(GetCurrentProcess(), pObject, GetCurrentProcess(), &hEvent, 0, FALSE,
471 DUPLICATE_SAME_ACCESS);
481 int GetEventFileDescriptor(HANDLE hEvent)
484 return winpr_Handle_getFd(hEvent);
495 int SetEventFileDescriptor(HANDLE hEvent,
int FileDescriptor, ULONG mode)
500 WINPR_EVENT*
event = NULL;
502 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
504 WLog_ERR(TAG,
"SetEventFileDescriptor: hEvent is not an event");
505 SetLastError(ERROR_INVALID_PARAMETER);
509 event = (WINPR_EVENT*)Object;
511 if (!event->bAttached && event->impl.fds[0] >= 0 && event->impl.fds[0] != FileDescriptor)
512 close(event->impl.fds[0]);
514 event->bAttached = TRUE;
515 event->common.Mode = mode;
516 event->impl.fds[0] = FileDescriptor;
533 void* GetEventWaitObject(HANDLE hEvent)
538 fd = GetEventFileDescriptor(hEvent);
539 obj = ((
void*)(
long)fd);
545 #if defined(WITH_DEBUG_EVENTS)
548 #include <sys/time.h>
549 #include <sys/resource.h>
551 static BOOL dump_handle_list(
void* data,
size_t index, va_list ap)
553 WINPR_EVENT*
event = data;
554 dump_event(event, index);
558 void DumpEventHandles_(
const char* fkt,
const char* file,
size_t line)
560 struct rlimit r = { 0 };
561 int rc = getrlimit(RLIMIT_NOFILE, &r);
565 for (rlim_t x = 0; x < r.rlim_cur; x++)
567 int flags = fcntl(x, F_GETFD);
571 WLog_INFO(TAG,
"------- limits [%d/%d] open files %" PRIuz, r.rlim_cur, r.rlim_max, count);
573 WLog_DBG(TAG,
"--------- Start dump [%s %s:%" PRIuz
"]", fkt, file, line);
574 if (global_event_list)
576 ArrayList_Lock(global_event_list);
577 ArrayList_ForEach(global_event_list, dump_handle_list);
578 ArrayList_Unlock(global_event_list);
580 WLog_DBG(TAG,
"--------- End dump [%s %s:%" PRIuz
"]", fkt, file, line);