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)
335 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
338 return CreateEventW(lpEventAttributes, manual, initial, lpName);
341HANDLE CreateEventExA(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName, DWORD dwFlags,
342 DWORD dwDesiredAccess)
344 BOOL initial = FALSE;
347 if (dwFlags & CREATE_EVENT_INITIAL_SET)
350 if (dwFlags & CREATE_EVENT_MANUAL_RESET)
353 if (dwDesiredAccess != 0)
354 WLog_WARN(TAG,
"[%s] does not support dwDesiredAccess 0x%08" PRIx32, lpName,
357 return CreateEventA(lpEventAttributes, manual, initial, lpName);
360HANDLE OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
363 WINPR_UNUSED(dwDesiredAccess);
364 WINPR_UNUSED(bInheritHandle);
365 WINPR_UNUSED(lpName);
366 WLog_ERR(TAG,
"not implemented");
370HANDLE OpenEventA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName)
373 WINPR_UNUSED(dwDesiredAccess);
374 WINPR_UNUSED(bInheritHandle);
375 WINPR_UNUSED(lpName);
376 WLog_ERR(TAG,
"not implemented");
380BOOL SetEvent(HANDLE hEvent)
384 WINPR_EVENT*
event = NULL;
386 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
388 WLog_ERR(TAG,
"SetEvent: hEvent is not an event");
389 SetLastError(ERROR_INVALID_PARAMETER);
393 event = (WINPR_EVENT*)Object;
394 return winpr_event_set(&event->impl);
397BOOL ResetEvent(HANDLE hEvent)
401 WINPR_EVENT*
event = NULL;
403 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
405 WLog_ERR(TAG,
"ResetEvent: hEvent is not an event");
406 SetLastError(ERROR_INVALID_PARAMETER);
410 event = (WINPR_EVENT*)Object;
411 return winpr_event_reset(&event->impl);
416HANDLE CreateFileDescriptorEventW(WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpEventAttributes,
417 BOOL bManualReset, WINPR_ATTR_UNUSED BOOL bInitialState,
418 int FileDescriptor, ULONG mode)
421 WINPR_EVENT*
event = NULL;
422 HANDLE handle = NULL;
423 event = (WINPR_EVENT*)calloc(1,
sizeof(WINPR_EVENT));
427 event->impl.fds[0] = -1;
428 event->impl.fds[1] = -1;
429 event->bAttached = TRUE;
430 event->bManualReset = bManualReset;
431 winpr_event_init_from_fd(&event->impl, FileDescriptor);
432 event->common.ops = &ops;
433 WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, mode);
434 handle = (HANDLE)event;
443HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
444 BOOL bInitialState,
int FileDescriptor, ULONG mode)
446 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
447 FileDescriptor, mode);
453HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
454 BOOL bInitialState,
void* pObject)
457 return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState,
458 (
int)(ULONG_PTR)pObject, WINPR_FD_READ);
460 HANDLE hEvent = NULL;
461 DuplicateHandle(GetCurrentProcess(), pObject, GetCurrentProcess(), &hEvent, 0, FALSE,
462 DUPLICATE_SAME_ACCESS);
472int GetEventFileDescriptor(HANDLE hEvent)
475 return winpr_Handle_getFd(hEvent);
486int SetEventFileDescriptor(HANDLE hEvent,
int FileDescriptor, ULONG mode)
491 WINPR_EVENT*
event = NULL;
493 if (!winpr_Handle_GetInfo(hEvent, &Type, &Object) || Type != HANDLE_TYPE_EVENT)
495 WLog_ERR(TAG,
"SetEventFileDescriptor: hEvent is not an event");
496 SetLastError(ERROR_INVALID_PARAMETER);
500 event = (WINPR_EVENT*)Object;
502 if (!event->bAttached && event->impl.fds[0] >= 0 && event->impl.fds[0] != FileDescriptor)
503 close(event->impl.fds[0]);
505 event->bAttached = TRUE;
506 event->common.Mode = mode;
507 event->impl.fds[0] = FileDescriptor;
524void* GetEventWaitObject(HANDLE hEvent)
529 fd = GetEventFileDescriptor(hEvent);
530 obj = ((
void*)(
long)fd);
536#if defined(WITH_DEBUG_EVENTS)
540#include <sys/resource.h>
542static BOOL dump_handle_list(
void* data,
size_t index, va_list ap)
544 WINPR_EVENT*
event = data;
545 dump_event(event, index);
549void DumpEventHandles_(
const char* fkt,
const char* file,
size_t line)
551 struct rlimit r = { 0 };
552 int rc = getrlimit(RLIMIT_NOFILE, &r);
556 for (rlim_t x = 0; x < r.rlim_cur; x++)
558 int flags = fcntl(x, F_GETFD);
562 WLog_INFO(TAG,
"------- limits [%d/%d] open files %" PRIuz, r.rlim_cur, r.rlim_max, count);
564 WLog_DBG(TAG,
"--------- Start dump [%s %s:%" PRIuz
"]", fkt, file, line);
565 if (global_event_list)
567 ArrayList_Lock(global_event_list);
568 ArrayList_ForEach(global_event_list, dump_handle_list);
569 ArrayList_Unlock(global_event_list);
571 WLog_DBG(TAG,
"--------- End dump [%s %s:%" PRIuz
"]", fkt, file, line);