void sxe_sync_ev_init(unsigned concurrency, void (*send_event)(void * sync, void * user_data)) { unsigned short port; SXEE82("sxe_sync_ev_init(concurrency=%u,send_event=%p)", concurrency, send_event); sxe_sync_ev_pool = sxe_pool_new("http_sync_ev", concurrency, sizeof(SXE_SYNC_EV), 2); sxe_sync_ev_sock = sxe_sync_ev_socket(); sxe_sync_generic_event = send_event; sxe_sync_ev_addr.sin_family = AF_INET; sxe_sync_ev_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); for (port = 1025; ; port++) { sxe_sync_ev_addr.sin_port = htons(port); if (bind(sxe_sync_ev_sock, (struct sockaddr *)&sxe_sync_ev_addr, sizeof(sxe_sync_ev_addr)) >= 0) { break; } SXEA12(port < USHRT_MAX, "Not able to bind any port between 1024 and %hu: %s", port, /* Coverage Exclusion - Assert */ sxe_socket_get_last_error_as_str()); } /* Coverage Exclusion - Not Reached */ SXEL81("Listening on port %hu", port); ev_io_init(&sxe_sync_ev_io, sxe_sync_ev_read, _open_osfhandle(sxe_sync_ev_sock, 0), EV_READ); ev_io_start(ev_default_loop(0), &sxe_sync_ev_io); SXER80("return"); }
static void select_modify (EV_P_ int fd, int oev, int nev) { SXEE83("select_modify(fd=%p, oev=%d, nev=%d)", fd, oev, nev); if (oev == nev) { SXER80("return // oev == nev"); return; } { #if EV_SELECT_USE_FD_SET #if EV_SELECT_IS_WINSOCKET SOCKET handle = anfds [fd].handle; #else int handle = fd; #endif SXEL80("#if EV_SELECT_USE_FD_SET"); SXEL81("handle = %d", handle); assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); /* FD_SET is broken on windows (it adds the fd to a set twice or more, * which eventually leads to overflows). Need to call it only on changes. */ #if EV_SELECT_IS_WINSOCKET if ((oev ^ nev) & EV_READ) { SXEL80("EV_SELECT_IS_WINSOCKET => (oev ^ nev) & EV_READ == TRUE"); #endif if (nev & EV_READ) { SXEL82("FD_SET(handle=%d, vec_ri=%p)", handle, vec_ri); FD_SET (handle, (fd_set *)vec_ri); } else { SXEL82("FD_CLR(handle=%d, vec_ri=%p)", handle, vec_ri); FD_CLR (handle, (fd_set *)vec_ri); } #if EV_SELECT_IS_WINSOCKET } #endif #if EV_SELECT_IS_WINSOCKET if ((oev ^ nev) & EV_WRITE) { SXEL80("EV_SELECT_IS_WINSOCKET => (oev ^ nev) & EV_WRITE == TRUE"); #endif if (nev & EV_WRITE) { SXEL82("FD_SET(handle=%d, vec_wi=%p)", handle, vec_wi); FD_SET (handle, (fd_set *)vec_wi); } else { SXEL82("FD_CLR(handle=%d, vec_wi=%p)", handle, vec_wi); FD_CLR (handle, (fd_set *)vec_wi); } #if EV_SELECT_IS_WINSOCKET } #endif SXEL80("#endif // EV_SELECT_USE_FD_SET"); #else SXEL80("#if *NOT* EV_SELECT_USE_FD_SET"); int word = fd / NFDBITS; fd_mask mask = 1UL << (fd % NFDBITS); if (expect_false (vec_max <= word)) { int new_max = word + 1; vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ #ifdef _WIN32 vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ #endif for (; vec_max < new_max; ++vec_max) ((fd_mask *)vec_ri) [vec_max] = ((fd_mask *)vec_wi) [vec_max] = 0; } ((fd_mask *)vec_ri) [word] |= mask; if (!(nev & EV_READ)) ((fd_mask *)vec_ri) [word] &= ~mask; ((fd_mask *)vec_wi) [word] |= mask; if (!(nev & EV_WRITE)) ((fd_mask *)vec_wi) [word] &= ~mask; SXEL80("#endif // *NOT* EV_SELECT_USE_FD_SET"); #endif } SXER80("return"); }
static void select_poll (EV_P_ ev_tstamp timeout) { struct timeval tv; int res; int fd_setsize; EV_RELEASE_CB; tv.tv_sec = (long)timeout; tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); #if EV_SELECT_USE_FD_SET fd_setsize = sizeof (fd_set); #else fd_setsize = vec_max * NFDBYTES; #endif SXEE81("select_poll(timeout=%f)", timeout); memcpy (vec_ro, vec_ri, fd_setsize); memcpy (vec_wo, vec_wi, fd_setsize); #ifdef _WIN32 SXEL80("Using select() on Windows"); /* pass in the write set as except set. * the idea behind this is to work around a windows bug that causes * errors to be reported as an exception and not by setting * the writable bit. this is so uncontrollably lame. */ memcpy (vec_eo, vec_wi, fd_setsize); res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); #elif EV_SELECT_USE_FD_SET SXEL80("Using select() with fd_set..."); fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); #else SXEL80("Using select() without fd_set..."); res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); #endif EV_ACQUIRE_CB; if (expect_false (res < 0)) { SXEL81("expect_false (res < 0) // res=%d", res); #if EV_SELECT_IS_WINSOCKET errno = WSAGetLastError (); SXEL81("errno=%d", errno); #endif #ifdef WSABASEERR /* on windows, select returns incompatible error codes, fix this */ if (errno >= WSABASEERR && errno < WSABASEERR + 1000) if (errno == WSAENOTSOCK) errno = EBADF; else errno -= WSABASEERR; SXEL81("errno=%d // after fixing error code", errno); #endif #ifdef _WIN32 /* select on windows errornously returns EINVAL when no fd sets have been * provided (this is documented). what microsoft doesn't tell you that this bug * exists even when the fd sets _are_ provided, so we have to check for this bug * here and emulate by sleeping manually. * we also get EINVAL when the timeout is invalid, but we ignore this case here * and assume that EINVAL always means: you have to wait manually. */ if (errno == EINVAL) { SXEL81("ev_sleep(timeout=%f)", timeout); ev_sleep (timeout); SXER80("return // errno == EINVAL"); return; } #endif if (errno == EBADF) fd_ebadf (EV_A); else if (errno == ENOMEM && !syserr_cb) fd_enomem (EV_A); else if (errno != EINTR) ev_syserr ("(libev) select"); SXER80("return // expect_false (res < 0)"); return; } #if EV_SELECT_USE_FD_SET { int fd; SXEL80("#if EV_SELECT_USE_FD_SET"); for (fd = 0; fd < anfdmax; ++fd) if (anfds [fd].events) { int events = 0; #if EV_SELECT_IS_WINSOCKET SOCKET handle = anfds [fd].handle; #else int handle = fd; #endif if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; #ifdef _WIN32 if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; #endif if (expect_true (events)) fd_event (EV_A_ fd, events); } SXEL80("#endif // EV_SELECT_USE_FD_SET"); } #else { int word, bit; SXEL80("#if *not* EV_SELECT_USE_FD_SET"); for (word = vec_max; word--; ) { fd_mask word_r = ((fd_mask *)vec_ro) [word]; fd_mask word_w = ((fd_mask *)vec_wo) [word]; #ifdef _WIN32 word_w |= ((fd_mask *)vec_eo) [word]; #endif if (word_r || word_w) for (bit = NFDBITS; bit--; ) { fd_mask mask = 1UL << bit; int events = 0; events |= word_r & mask ? EV_READ : 0; events |= word_w & mask ? EV_WRITE : 0; if (expect_true (events)) fd_event (EV_A_ word * NFDBITS + bit, events); } } SXEL80("#endif // *not* EV_SELECT_USE_FD_SET"); } #endif SXER80("return"); }