BOOST_LOG_ONCE_BLOCK() { if (!InitializeSecurityDescriptor(&g_unrestricted_security_descriptor, SECURITY_DESCRIPTOR_REVISION)) { DWORD err = GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to initialize security descriptor", (err)); } if (!SetSecurityDescriptorDacl(&g_unrestricted_security_descriptor, TRUE, NULL, FALSE)) { DWORD err = GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to set null DACL to a security descriptor", (err)); } g_unrestricted_security_attributes.nLength = sizeof(g_unrestricted_security_attributes); g_unrestricted_security_attributes.lpSecurityDescriptor = &g_unrestricted_security_descriptor; g_unrestricted_security_attributes.bInheritHandle = FALSE; }
bool interprocess_condition_variable::wait(interprocess_mutex::optional_unlock& lock, boost::detail::winapi::HANDLE_ abort_handle) { int32_t waiters = m_shared_state->m_waiters; if (waiters < 0) { // We need to select a new semaphore to block on m_current_semaphore = get_unused_semaphore(); ++m_shared_state->m_generation; m_shared_state->m_semaphore_id = m_current_semaphore->m_id; waiters = 0; } else { // Avoid integer overflow if (BOOST_UNLIKELY(waiters >= ((std::numeric_limits< int32_t >::max)() - 1))) BOOST_LOG_THROW_DESCR(limitation_error, "Too many waiters on an interprocess condition variable"); // Make sure we use the right semaphore to block on const uint32_t id = m_shared_state->m_semaphore_id; if (m_current_semaphore->m_id != id) m_current_semaphore = get_semaphore(id); } m_shared_state->m_waiters = waiters + 1; const uint32_t generation = m_shared_state->m_generation; boost::detail::winapi::HANDLE_ handles[2u] = { m_current_semaphore->m_semaphore.get_handle(), abort_handle }; interprocess_mutex* const mutex = lock.disengage(); mutex->unlock(); boost::detail::winapi::DWORD_ retval = boost::detail::winapi::WaitForMultipleObjects(2u, handles, false, boost::detail::winapi::INFINITE_); if (BOOST_UNLIKELY(retval == boost::detail::winapi::WAIT_FAILED_)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); // Although highly unrealistic, it is possible that it took so long for the current thread to enter WaitForMultipleObjects that // another thread has managed to destroy the semaphore. This can happen if the semaphore remains in a non-zero state // for too long, which means that another process died while being blocked on the semaphore, and the semaphore was signalled, // and the non-zero state timeout has passed. In this case the most logical behavior for the wait function is to return as // if because of a wakeup. if (err == ERROR_INVALID_HANDLE) retval = boost::detail::winapi::WAIT_OBJECT_0_; else BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to block on an interprocess semaphore object", (err)); } // Have to unconditionally lock the mutex here mutex->lock(); lock.engage(*mutex); if (generation == m_shared_state->m_generation && m_shared_state->m_waiters > 0) --m_shared_state->m_waiters; return retval == boost::detail::winapi::WAIT_OBJECT_0_; }
void interprocess_semaphore::open(const wchar_t* name) { boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenSemaphoreW(boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ | boost::detail::winapi::SEMAPHORE_QUERY_STATE_, false, name); if (BOOST_UNLIKELY(h == NULL)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to open an interprocess semaphore object", (err)); } m_sem.init(h); }
bool interprocess_semaphore::is_semaphore_zero_count_emulated(boost::detail::winapi::HANDLE_ h) { const boost::detail::winapi::DWORD_ retval = boost::detail::winapi::WaitForSingleObject(h, 0u); if (retval == boost::detail::winapi::wait_timeout) { return true; } else if (BOOST_UNLIKELY(retval != boost::detail::winapi::wait_object_0)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to test an interprocess semaphore object for zero count", (err)); } // Restore the decremented counter BOOST_VERIFY(!!boost::detail::winapi::ReleaseSemaphore(h, 1, NULL)); return false; }
bool interprocess_semaphore::is_semaphore_zero_count_nt_query_semaphore(boost::detail::winapi::HANDLE_ h) { semaphore_basic_information info = {}; NTSTATUS_ err = nt_query_semaphore ( h, 0u, // SemaphoreBasicInformation &info, sizeof(info), NULL ); if (BOOST_UNLIKELY(err != 0u)) { char buf[sizeof(unsigned int) * 2u + 4u]; boost::log::aux::snprintf(buf, sizeof(buf), "0x%08x", static_cast< unsigned int >(err)); BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, std::string("Failed to test an interprocess semaphore object for zero count, NT status: ") + buf, (ERROR_INVALID_HANDLE)); } return info.current_count == 0u; }
void interprocess_semaphore::create_or_open(const wchar_t* name, permissions const& perms) { #if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 boost::detail::winapi::HANDLE_ h = boost::detail::winapi::CreateSemaphoreExW ( reinterpret_cast< boost::detail::winapi::SECURITY_ATTRIBUTES_* >(perms.get_native()), 0, // initial count (std::numeric_limits< boost::detail::winapi::LONG_ >::max)(), // max count name, 0u, // flags boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ | boost::detail::winapi::SEMAPHORE_QUERY_STATE_ ); #else boost::detail::winapi::HANDLE_ h = boost::detail::winapi::CreateSemaphoreW ( reinterpret_cast< boost::detail::winapi::SECURITY_ATTRIBUTES_* >(perms.get_native()), 0, // initial count (std::numeric_limits< boost::detail::winapi::LONG_ >::max)(), // max count name ); #endif if (h == NULL) { boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); if (BOOST_LIKELY(err == ERROR_ALREADY_EXISTS)) { open(name); return; } else { BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to create an interprocess semaphore object", (err)); } } m_sem.init(h); }
/*! * The callback for greater relation filter */ virtual filter on_greater_relation(attribute_name const& name, string_type const& arg) { BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The greater attribute value relation is not supported", (name)); BOOST_LOG_UNREACHABLE(); }
/*! * The callback for custom relation filter */ virtual filter on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg) { BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The custom attribute value relation \"" + boost::log::aux::to_narrow(arg) + "\" is not supported", (name)); BOOST_LOG_UNREACHABLE(); }
/*! * The callback for less relation filter */ virtual filter on_less_relation(attribute_name const& name, string_type const& arg) { BOOST_LOG_THROW_DESCR_PARAMS(parse_error, "The less attribute value relation is not supported", (name)); BOOST_LOG_UNREACHABLE_RETURN(filter()); }