inline bool wait_until( const child_handle &p, int & exit_code, const std::chrono::time_point<Clock, Duration>& time_out, std::error_code & ec) noexcept { pid_t ret; int status; bool timed_out; do { ret = ::waitpid(p.pid, &status, WNOHANG); if (ret == 0) { timed_out = Clock::now() >= time_out; if (timed_out) return false; } } while ((ret == 0) || (((ret == -1) && errno == EINTR) || ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)))); if (ret == -1) ec = boost::process::detail::get_last_error(); else { ec.clear(); exit_code = status; } return true; }
addrinfo_ptr getaddrinfo(const char * host, const char * service, std::error_code & err) { addrinfo_type hints; std::memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; int res; addrinfo_type * ptr; do res = ::getaddrinfo(host, service, &hints, &ptr); while (res == EAI_AGAIN); if (res == 0) { err.clear(); return addrinfo_ptr(ptr); } if (res == EAI_SYSTEM) { err.assign(errno, std::generic_category()); return addrinfo_ptr(nullptr); } else { err.assign(res, gai_error_category()); return addrinfo_ptr(nullptr); } }
bool GlContext::makeNotCurrent(std::error_code& ec) { ec.clear(); std::mutex* mutex; auto threadid = std::this_thread::get_id(); auto& map = contextCurrentMap(mutex); decltype(map.begin()) thisThreadIt {}; //check if it is already not current { std::lock_guard<std::mutex> lock(*mutex); thisThreadIt = map.find(threadid); if(thisThreadIt == map.end()) thisThreadIt = map.insert({threadid, {}}).first; if(thisThreadIt->second.first != this) { ec = Errc::contextAlreadyNotCurrent; return true; } } if(!makeNotCurrentImpl(ec)) return false; std::lock_guard<std::mutex> lock(*mutex); thisThreadIt->second = {nullptr, nullptr}; return true; }
space_info space(const std::string& path, std::error_code& ec) { using WINDOWS::ToW; ec.clear(); space_info sp; auto pathW = ToW(path); ULARGE_INTEGER capacity; ULARGE_INTEGER available; ULARGE_INTEGER free; auto result = GetDiskFreeSpaceExW(pathW.c_str(), &available, &capacity, &free); if (result == FALSE) { ec.assign(GetLastError(), std::system_category()); sp.available = static_cast<uintmax_t>(-1); sp.capacity = static_cast<uintmax_t>(-1); sp.free = static_cast<uintmax_t>(-1); return sp; } sp.available = static_cast<uintmax_t>(available.QuadPart); sp.capacity = static_cast<uintmax_t>(capacity.QuadPart); sp.free = static_cast<uintmax_t>(free.QuadPart); return sp; }
inline bool wait_until( child_handle &p, int & exit_code, const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code &ec) noexcept { std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>( timeout_time - std::chrono::system_clock::now()); ::boost::detail::winapi::DWORD_ _exit_code = 1; if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(), static_cast<::boost::detail::winapi::DWORD_>(ms.count())) == ::boost::detail::winapi::wait_failed) ec = std::error_code( ::boost::detail::winapi::GetLastError(), std::system_category()); else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) ec = std::error_code( ::boost::detail::winapi::GetLastError(), std::system_category()); else ec.clear(); exit_code = static_cast<int>(exit_code); ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess); p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_; return true; ; }
bool GlxContext::swapInterval(int interval, std::error_code& ec) const { //TODO: check for interval < 0 and tear extensions not supported. ec.clear(); if(!GLAD_GLX_EXT_swap_control || !glXSwapIntervalEXT) { ec = {GlContextErrc::extensionNotSupported}; return false; } const GlSurface* currentSurface; GlContext::current(¤tSurface); auto currentGlxSurface = dynamic_cast<const GlxSurface*>(currentSurface); if(!currentGlxSurface) { // ec = {GlContextErrorCode::surfaceNotCurrent}; //TODO: add error for this case return false; } ::glXSwapIntervalEXT(xDisplay(), currentGlxSurface->xDrawable(), interval); //TODO: handle possible error into ec return true; }
inline void terminate(const group_handle &p, std::error_code &ec) noexcept { if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE)) ec = boost::process::detail::get_last_error(); else ec.clear(); }
file_status link_status(path p, struct stat& st, std::error_code& ec) { if (::stat(p.c_str(), &st) != 0) { if (errno == ENOENT) { ec.clear(); return file_status{file_type::not_found, perms::none}; } else { ec = {errno, std::system_category()}; return {}; } } ec.clear(); file_type type = to_file_type(st, ec); perms prms = static_cast<perms>(st.st_mode) & perms::mask; return file_status{type, prms}; }
bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept { auto t = status(to, ec); if (!is_regular_file(from) || (t.type() != file_type::not_found && (t.type() != file_type::regular || equivalent(from, to) || (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none))) { ec.assign(EEXIST, std::system_category()); } else { if (t.type() == file_type::not_found || (options & copy_options::overwrite_existing) != copy_options::none || ((options & copy_options::update_existing) != copy_options::none && last_write_time(from) > last_write_time(to))) { std::ifstream src(from, std::ios::binary); std::ofstream dst(to, std::ios::binary | std::ios::trunc); dst << src.rdbuf(); if (errno != 0) { ec = {errno, std::system_category()}; } else { ec.clear(); return true; } } } return false; }
inline bool wait_for( const group_handle &p, const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept { pid_t ret; int status; auto start = std::chrono::system_clock::now(); auto time_out = start + rel_time; bool time_out_occured = false; do { ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG); if (std::chrono::system_clock::now() >= time_out) { time_out_occured = true; break; } } while (((ret == -1) && errno == EINTR) || ((ret != -1) && !WIFEXITED(status))); if (ret == -1) ec = boost::process::detail::get_last_error(); else ec.clear(); return !time_out_occured; }
void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept { if (::truncate(p.c_str(), static_cast<off_t>(size))) { ec = {errno, std::system_category()}; } else { ec.clear(); } }
void rename(const path& from, const path& to, std::error_code& ec) noexcept { if (::rename(from.c_str(), to.c_str())) { ec = {errno, std::system_category()}; } else { ec.clear(); } }
void current_path(const path& p, std::error_code& ec) noexcept { if (chdir(p.c_str()) == 0) { ec = {errno, std::system_category()}; } else { ec.clear(); } }
uintmax_t hard_link_count(struct stat st, std::error_code& ec) { if (ec.value() == 0) { ec.clear(); } else { return 0; } return st.st_nlink; }
void state_machine_t::shutdown(std::error_code ec) { if (shutdowned.exchange(true)) { return; } auto state = *this->state.synchronize(); COCAINE_LOG_DEBUG(log, "slave is shutting down from state %s: %s", state->name(), ec.message()); state->cancel(); if(state->terminating()) { // We don't consider any reason for termination in "terminating" state as an error ec.clear(); } migrate(std::make_shared<stopped_t>(ec)); fetcher.apply([&](std::shared_ptr<fetcher_t>& fetcher) { fetcher->close(); fetcher.reset(); }); if (ec && ec != error::overseer_shutdowning) { dump(); } data.channels.apply([&](channels_map_t& channels) { const auto size = channels.size(); if (size > 0) { COCAINE_LOG_WARNING(log, "slave is dropping %d sessions", size); } for (auto& channel : channels) { loop.post([=]() { channel.second->close_both(); }); } channels.clear(); }); // Check if the slave has been terminated externally. If so, do not call the cleanup callback. if (closed) { return; } // NOTE: To prevent deadlock between session.channels and overseer.pool. Consider some // other solution. const auto cleanup_handler = cleanup; loop.post([=]() { try { cleanup_handler(ec); } catch (const std::exception& err) { // Just eat an exception, we don't care why the cleanup handler failed to do its job. COCAINE_LOG_WARNING(log, "unable to cleanup after slave's death: %s", err.what()); } }); }
uintmax_t file_size(struct stat st, std::error_code& ec) { if (ec.value() == 0) { ec.clear(); } else { return 0; } return st.st_size; }
path current_path(std::error_code& ec) { char temp[PATH_MAX]; if (::getcwd(temp, PATH_MAX) == nullptr) { ec = {errno, std::system_category()}; } else { ec.clear(); } return path(temp); }
path canonical(const path& p, std::error_code& ec) { char tmp[PATH_MAX]; if (realpath(p.c_str(), tmp) == nullptr) { ec = {errno, std::system_category()}; } else { ec.clear(); } return path(tmp); }
inline void terminate(const child_handle &p, std::error_code &ec) noexcept { if (::kill(p.pid, SIGKILL) == -1) ec = boost::process::detail::get_last_error(); else ec.clear(); int status; ::waitpid(p.pid, &status, 0); //just to clean it up }
bool create_directory(const path& p, std::error_code& ec) noexcept { auto error = mkdir(p.c_str(), static_cast<int>(perms::all)); if (error && !is_directory(p)) { ec = {errno, std::system_category()}; } else { ec.clear(); } return !error; }
struct stat lstat(path p, std::error_code& ec) { struct stat st; if (::lstat(p.c_str(), &st) != 0) { ec = {errno, std::system_category()}; } else { ec.clear(); } return st; }
inline void terminate(child_handle &p, std::error_code &ec) noexcept { if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE)) ec = boost::process::detail::get_last_error(); else { ec.clear(); ::boost::detail::winapi::CloseHandle(p.proc_info.hProcess); p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_; } }
/// Manually close the file descriptor void close(std::error_code& ec) noexcept { ec.clear(); errno = 0; if (::close(fd_) == 0) { fd_ = -1; delete_ = false; } else { ec.assign(errno, std::system_category()); } }
bool remove(const path& p, std::error_code& ec) noexcept { if (!exists(p, ec)) return false; if (::remove(p.c_str())) { ec = {errno, std::system_category()}; return false; } else { ec.clear(); return true; } }
bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept { struct stat st1; struct stat st2; if (::stat(p1.c_str(), &st1) || ::stat(p2.c_str(), &st2)) { ec = {errno, std::system_category()}; return false; } else { ec.clear(); return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino; } }
bool GlxContext::makeNotCurrentImpl(std::error_code& ec) { ec.clear(); if(!::glXMakeCurrent(xDisplay(), 0, nullptr)) { //TODO: handle error into ec warning("ny::GlxContext::makeNotCurrentImpl (glXMakeCurrent) failed"); return false; } return true; }
bool GlxContext::makeCurrentImpl(const GlSurface& surface, std::error_code& ec) { ec.clear(); auto drawable = dynamic_cast<const GlxSurface*>(&surface)->xDrawable(); if(!::glXMakeCurrent(xDisplay(), drawable, glxContext_)) { //TODO: handle error into ec warning("ny::GlxContext::makeCurrentImpl (glXMakeCurrent) failed"); return false; } return true; }
::std::string font_resource_factory::font_family(::std::error_code& ec) const noexcept { ::std::string s; try { s = _Family; } catch (const ::std::bad_alloc&) { ec = make_error_code(errc::not_enough_memory); return s; } catch (const ::std::length_error&) { ec = make_error_code(errc::not_enough_memory); return s; } ec.clear(); return s; }
file_time_type last_write_time(struct stat st, std::error_code& ec) { if (ec.value() == 0) { ec.clear(); } else { return {}; } #if __APPLE__ return file_time_type() + std::chrono::duration_cast<file_time_type::duration>( std::chrono::nanoseconds(st.st_mtimespec.tv_nsec)); #else return file_time_type() + std::chrono::duration_cast<file_time_type::duration>( std::chrono::nanoseconds(st.st_mtim.tv_nsec)); #endif }
inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept { ::boost::detail::winapi::DWORD_ code; //single value, not needed in the winapi. if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code)) ec = ::boost::process::detail::get_last_error(); else ec.clear(); if (code == still_active) return true; else { exit_code = code; return false; } }