core::curl_handler::connection_context::connection_context(milliseconds_t _timeout, curl_handler* _curl_handler, CURL* _easy_handle, const completion_handler_t& _completion_handler) : timeout_(_timeout) , curl_handler_(_curl_handler) , easy_handle_(_easy_handle) , completion_handler_(_completion_handler) , socket_(0) , event_(nullptr) { const auto tv = make_timeval(timeout_); timeout_event_ = evtimer_new(curl_handler_->event_base_, event_timeout_callback, this); evtimer_add(timeout_event_, &tv); }
bool winsock2_streambuf::wait_state(time_point until, int fstate) { int wsaerr; int solen; again: struct timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set read_set, write_set, err_set; fd_set * pread_set = nullptr; fd_set * pwrite_set = nullptr; if (fstate & freadable) { pread_set = &read_set; FD_ZERO(pread_set); FD_SET(m_sockhandle, pread_set); } if (fstate & fwritable) { pwrite_set = &write_set; FD_ZERO(pwrite_set); FD_SET(m_sockhandle, pwrite_set); } FD_ZERO(&err_set); FD_SET(m_sockhandle, &err_set); int res = ::select(m_sockhandle + 1, pread_set, pwrite_set, &err_set, &timeout); if (res == 0) // timeout { m_lasterror = make_error_code(sock_errc::timeout); return false; } if (res == -1) goto sockerror; assert(res >= 1); solen = sizeof(wsaerr); res = ::getsockopt(m_sockhandle, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&wsaerr), &solen); if (res != 0) goto sockerror; if (wsaerr != 0) goto wsaerror; return true; sockerror: wsaerr = ::WSAGetLastError(); wsaerror: if (rw_error(-1, wsaerr, m_lasterror)) return false; goto again; }
bool bsdsock_streambuf::wait_state(time_point until, int fstate) { int err; sockoptlen_t solen; again: struct timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set read_set, write_set; fd_set * pread_set = nullptr; fd_set * pwrite_set = nullptr; if (fstate & freadable) { pread_set = &read_set; FD_ZERO(pread_set); FD_SET(m_sockhandle, pread_set); } if (fstate & fwritable) { pwrite_set = &write_set; FD_ZERO(pwrite_set); FD_SET(m_sockhandle, pwrite_set); } int res = ::select(m_sockhandle + 1, pread_set, pwrite_set, nullptr, &timeout); if (res == 0) // timeout { m_lasterror = make_error_code(sock_errc::timeout); return false; } if (res == -1) goto sockerror; solen = sizeof(err); res = ::getsockopt(m_sockhandle, SOL_SOCKET, SO_ERROR, &err, &solen); if (res != 0) goto sockerror; if (err != 0) goto error; return true; sockerror: err = errno; error: if (rw_error(-1, err, m_lasterror)) return false; goto again; }
static void set_alarm (void) { if (atimers) { #ifdef HAVE_SETITIMER struct itimerval it; #endif struct timespec now, interval; #ifdef HAVE_ITIMERSPEC if (0 <= timerfd || alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; # ifdef HAVE_TIMERFD if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) { add_timer_wait_descriptor (timerfd); return; } # endif if (alarm_timer_ok && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) return; } #endif /* Determine interval till the next timer is ripe. Don't set the interval to 0; this disables the timer. */ now = current_timespec (); interval = (timespec_cmp (atimers->expiration, now) <= 0 ? make_timespec (0, 1000 * 1000) : timespec_sub (atimers->expiration, now)); #ifdef HAVE_SETITIMER memset (&it, 0, sizeof it); it.it_value = make_timeval (interval); setitimer (ITIMER_REAL, &it, 0); #else /* not HAVE_SETITIMER */ alarm (max (interval.tv_sec, 1)); #endif /* not HAVE_SETITIMER */ } }
static void set_alarm (void) { if (atimers) { #ifdef HAVE_SETITIMER struct itimerval it; #endif EMACS_TIME now, interval; #ifdef HAVE_ITIMERSPEC if (alarm_timer_ok) { struct itimerspec ispec; ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; if (timer_settime (alarm_timer, 0, &ispec, 0) == 0) return; } #endif /* Determine interval till the next timer is ripe. Don't set the interval to 0; this disables the timer. */ now = current_emacs_time (); interval = (EMACS_TIME_LE (atimers->expiration, now) ? make_emacs_time (0, 1000 * 1000) : sub_emacs_time (atimers->expiration, now)); #ifdef HAVE_SETITIMER memset (&it, 0, sizeof it); it.it_value = make_timeval (interval); setitimer (ITIMER_REAL, &it, 0); #else /* not HAVE_SETITIMER */ alarm (max (EMACS_SECS (interval), 1)); #endif /* not HAVE_SETITIMER */ } }
bool winsock2_streambuf::do_sockconnect(handle_type sock, const addrinfo_type * addr) { int wsaerr, res, solen; StateType prevstate; bool closesock, pubres; // в случае ошибки закрыть сокет auto until = time_point::clock::now() + m_timeout; prevstate = Closed; m_lasterror.clear(); res = ::connect(sock, addr->ai_addr, addr->ai_addrlen); if (res == 0) goto connected; // connected immediately assert(res == SOCKET_ERROR); if ((wsaerr = ::WSAGetLastError()) != WSAEWOULDBLOCK) goto wsaerror; again: pubres = publish_connecting(sock); if (!pubres) goto intrreq; timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set write_set, err_set; FD_ZERO(&write_set); FD_ZERO(&err_set); FD_SET(sock, &write_set); FD_SET(sock, &err_set); prevstate = Connecting; res = ::select(0, nullptr, &write_set, &err_set, &timeout); if (res == 0) // timeout { wsaerr = WSAETIMEDOUT; goto wsaerror; } if (res == SOCKET_ERROR) goto sockerror; assert(res == 1); solen = sizeof(wsaerr); res = ::getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&wsaerr), &solen); if (res != 0) goto sockerror; if (wsaerr != 0) goto wsaerror; connected: pubres = publish_opened(sock, prevstate); if (!pubres) goto intrreq; m_lasterror.clear(); return true; sockerror: wsaerr = ::WSAGetLastError(); wsaerror: pubres = m_state.compare_exchange_strong(prevstate, Closed, std::memory_order_relaxed); // произошла ошибка, она может результатом closesocket из interrupt // если мы успешно перешли в Closed - interrupt'а не было, а значит это обычная ошибка if (pubres) { if (wsaerr == WSAEINTR) goto again; closesock = true; if (wsaerr == WSAETIMEDOUT) m_lasterror = make_error_code(sock_errc::timeout); else m_lasterror.assign(wsaerr, std::system_category()); } else intrreq: { // было прерывание, если оно было до publish_connecting, то мы должны закрыть сокет // иначе сокет был закрыт из interrupt m_lasterror = std::make_error_code(std::errc::interrupted); // такое возможно, только если мы не смогли опубликовать publish_connecting, closesock = prevstate == Closed; } if (closesock) { res = ::closesocket(m_sockhandle); assert(res == 0 || (res = ::WSAGetLastError()) == 0); } m_sockhandle = INVALID_SOCKET; return false; }
bool bsdsock_streambuf::do_sockconnect(handle_type sock, const addrinfo_type * addr) { int err, res, pipefd[2]; // self pipe trick. [0] readable, [1] writable bool closepipe, pubres; // должны ли мы закрыть pipe, или он был закрыт в interrupt sockoptlen_t solen; StateType prevstate; auto until = time_point::clock::now() + m_timeout; prevstate = Closed; m_lasterror.clear(); res = ::pipe(pipefd); if (res != 0) goto sockerror; res = ::connect(sock, addr->ai_addr, addr->ai_addrlen); if (res == 0) goto connected; // connected immediately assert(res == -1); if ((err = errno) != EINPROGRESS) goto error; again: pubres = publish_connecting(pipefd[1]); if (!pubres) goto intrreq; struct timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set write_set, read_set; FD_ZERO(&write_set); FD_ZERO(&read_set); FD_SET(sock, &write_set); FD_SET(pipefd[0], &read_set); prevstate = Connecting; res = ::select(std::max(sock, pipefd[0]) + 1, &read_set, &write_set, nullptr, &timeout); if (res == 0) // timeout { err = ETIMEDOUT; goto error; } if (res == -1) goto sockerror; assert(res >= 1); solen = sizeof(err); res = ::getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &solen); if (res != 0) goto sockerror; if (err != 0) goto error; connected: pubres = publish_opened(sock, prevstate); if (!pubres) goto intrreq; m_lasterror.clear(); return true; sockerror: err = errno; error: pubres = m_state.compare_exchange_strong(prevstate, Closed, std::memory_order_relaxed); // произошла ошибка, она может результатом closesocket из interrupt // если мы успешно перешли в Closed - interrupt'а не было, а значит это обычная ошибка if (pubres) { if (err == EINTR) goto again; closepipe = true; if (err == ETIMEDOUT) m_lasterror = make_error_code(sock_errc::timeout); else m_lasterror.assign(err, std::generic_category()); } else intrreq: { // было прерывание, если оно было до publish_connecting, то мы должны закрыть pipefd[1] // иначе pipefd[1] был закрыт внутри interrupt m_lasterror = std::make_error_code(std::errc::interrupted); // такое возможно, только если мы не смогли опубликовать publish_connecting, closepipe = prevstate == Closed; } if (closepipe) ::close(pipefd[1]); ::close(pipefd[0]); res = ::close(sock); assert(res == 0 || (res = errno) == 0); m_sockhandle = -1; return false; }
static enum profiler_cpu_running setup_cpu_timer (Lisp_Object sampling_interval) { struct sigaction action; struct itimerval timer; struct timespec interval; int billion = 1000000000; if (! RANGED_INTEGERP (1, sampling_interval, (TYPE_MAXIMUM (time_t) < EMACS_INT_MAX / billion ? ((EMACS_INT) TYPE_MAXIMUM (time_t) * billion + (billion - 1)) : EMACS_INT_MAX))) return NOT_RUNNING; current_sampling_interval = XINT (sampling_interval); interval = make_timespec (current_sampling_interval / billion, current_sampling_interval % billion); emacs_sigaction_init (&action, deliver_profiler_signal); sigaction (SIGPROF, &action, 0); #ifdef HAVE_ITIMERSPEC if (! profiler_timer_ok) { /* System clocks to try, in decreasing order of desirability. */ static clockid_t const system_clock[] = { #ifdef CLOCK_THREAD_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID, #endif #ifdef CLOCK_PROCESS_CPUTIME_ID CLOCK_PROCESS_CPUTIME_ID, #endif #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC, #endif CLOCK_REALTIME }; int i; struct sigevent sigev; sigev.sigev_value.sival_ptr = &profiler_timer; sigev.sigev_signo = SIGPROF; sigev.sigev_notify = SIGEV_SIGNAL; for (i = 0; i < ARRAYELTS (system_clock); i++) if (timer_create (system_clock[i], &sigev, &profiler_timer) == 0) { profiler_timer_ok = 1; break; } } if (profiler_timer_ok) { struct itimerspec ispec; ispec.it_value = ispec.it_interval = interval; if (timer_settime (profiler_timer, 0, &ispec, 0) == 0) return TIMER_SETTIME_RUNNING; } #endif #ifdef HAVE_SETITIMER timer.it_value = timer.it_interval = make_timeval (interval); if (setitimer (ITIMER_PROF, &timer, 0) == 0) return SETITIMER_RUNNING; #endif return NOT_RUNNING; }