Beispiel #1
0
filter default_filter_factory< CharT >::parse_argument(attribute_name const& name, string_type const& arg)
{
    typedef log::aux::encoding_specific< typename log::aux::encoding< char_type >::type > encoding_specific;
    const qi::real_parser< double, qi::strict_real_policies< double > > real_;

    filter f;
    const on_fp_argument< RelationT > on_fp(name, f);
    const on_integral_argument< RelationT > on_int(name, f);
    const on_string_argument< RelationT > on_str(name, f);

    const bool res = qi::parse
    (
        arg.c_str(), arg.c_str() + arg.size(),
        (
            real_[boost::log::as_action(on_fp)] |
            qi::long_[boost::log::as_action(on_int)] |
            qi::as< string_type >()[ +encoding_specific::print ][boost::log::as_action(on_str)]
        ) >> qi::eoi
    );

    if (!res)
        BOOST_LOG_THROW_DESCR(parse_error, "Failed to parse relation operand");

    return boost::move(f);
}
BOOST_LOG_EXPORT void basic_event_log_backend< CharT >::construct(
    boost::log::aux::universal_path const& message_file_name,
    string_type const& target,
    string_type const& log_name,
    string_type const& source_name,
    event_log::registration_mode reg_mode)
{
    if (reg_mode != event_log::never)
    {
        aux::registry_params< char_type > reg_params;
        string_type file_name;
        log::aux::code_convert(message_file_name.string(), file_name);
        reg_params.event_message_file = file_name;
        reg_params.types_supported = DWORD(
            EVENTLOG_SUCCESS |
            EVENTLOG_INFORMATION_TYPE |
            EVENTLOG_WARNING_TYPE |
            EVENTLOG_ERROR_TYPE);
        aux::init_event_log_registry(log_name, source_name, reg_mode == event_log::forced, reg_params);
    }

    std::auto_ptr< implementation > p(new implementation());

    const char_type* target_unc = NULL;
    if (!target.empty())
        target_unc = target.c_str();

    HANDLE hSource = register_event_source(target_unc, source_name.c_str());
    if (!hSource)
        BOOST_LOG_THROW_DESCR(system_error, "Could not register event source");

    p->m_SourceHandle = hSource;

    m_pImpl = p.release();
}
//! The method creates the backend implementation
BOOST_LOG_API void syslog_backend::construct(syslog::facility fac, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident)
{
#ifdef BOOST_LOG_USE_NATIVE_SYSLOG
    if (use_impl == syslog::native)
    {
        typedef implementation::native native_impl;
        m_pImpl = new native_impl(fac, ident);
        return;
    }
#endif // BOOST_LOG_USE_NATIVE_SYSLOG

#if !defined(BOOST_LOG_NO_ASIO)
    typedef implementation::udp_socket_based udp_socket_based_impl;
    switch (ip_version)
    {
    case v4:
        m_pImpl = new udp_socket_based_impl(fac, asio::ip::udp::v4());
        break;
    case v6:
        m_pImpl = new udp_socket_based_impl(fac, asio::ip::udp::v6());
        break;
    default:
        BOOST_LOG_THROW_DESCR(setup_error, "Incorrect IP version specified");
    }
#endif
}
Beispiel #4
0
 static void allocate(StorageT& stg)
 {
     if (pthread_key_create(reinterpret_cast< pthread_key_type* >(&stg.as_dword), 0) != 0)
     {
         BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
     }
 }
 //! Initializing constructor
 scoped_thread_id(frontend_mutex_type& mut, condition_variable_any& cond, thread::id& tid, boost::atomic< bool >& sr)
     : m_Mutex(mut), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr)
 {
     lock_guard< frontend_mutex_type > lock(m_Mutex);
     if (m_ThreadID != thread::id())
         BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread");
     m_ThreadID = this_thread::get_id();
 }
thread_specific_base::thread_specific_base()
{
    m_Key = TlsAlloc();
    if (BOOST_UNLIKELY(m_Key == TLS_OUT_OF_INDEXES))
    {
        BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
    }
}
Beispiel #7
0
 //! Initializing constructor
 scoped_thread_id(unique_lock< frontend_mutex_type >& l, condition_variable_any& cond, thread::id& tid, bool volatile& sr)
     : m_Mutex(*l.mutex()), m_Cond(cond), m_ThreadID(tid), m_StopRequested(sr)
 {
     unique_lock< frontend_mutex_type > lock(move(l));
     if (m_ThreadID != thread::id())
         BOOST_LOG_THROW_DESCR(unexpected_call, "Asynchronous sink frontend already runs a record feeding thread");
     m_ThreadID = this_thread::get_id();
 }
Beispiel #8
0
thread_specific_base::thread_specific_base()
{
    m_Key.as_dword = TlsAlloc();
    if (m_Key.as_dword == TLS_OUT_OF_INDEXES)
    {
        BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
    }
    set_content(0);
}
Beispiel #9
0
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_;
}
 static void allocate(void*& stg)
 {
     pthread_key_type key = NULL;
     const int res = pthread_key_create(&key, NULL);
     if (BOOST_UNLIKELY(res != 0))
     {
         BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
     }
     stg = static_cast< void* >(key);
 }
 static void allocate(void*& stg)
 {
     pthread_key_caster caster = {};
     const int res = pthread_key_create(&caster.as_key, NULL);
     if (BOOST_UNLIKELY(res != 0))
     {
         BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
     }
     stg = caster.as_storage;
 }
Beispiel #12
0
 static void allocate(StorageT& stg)
 {
     pthread_key_type* pkey = new pthread_key_type;
     if (pthread_key_create(pkey, 0) != 0)
     {
         delete pkey;
         BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
     }
     stg.as_pointer = pkey;
 }
 static void allocate(void*& stg)
 {
     pthread_key_type* pkey = new pthread_key_type();
     const int res = pthread_key_create(pkey, NULL);
     if (BOOST_UNLIKELY(res != 0))
     {
         delete pkey;
         BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted");
     }
     stg = pkey;
 }
    //! The method returns the filter factory for the specified attribute name
    formatter_factory_type& get_factory(attribute_name const& name) const
    {
        typename factories_map::const_iterator it = m_Map.find(name);
        if (it != m_Map.end())
        {
            return *it->second;
        }
        else
        {
#if !defined(BOOST_LOG_WITHOUT_DEFAULT_FACTORIES)
            return m_DefaultFactory;
#else
            BOOST_LOG_THROW_DESCR(setup_error, "No formatter factory registered for attribute " + name.string());
#endif
        }
    }
Beispiel #15
0
    std::basic_string< CharT > get_current_module_name()
    {
        static HMODULE hSelfModule = 0;

        BOOST_LOG_ONCE_BLOCK()
        {
            init_self_module_handle(hSelfModule);
        }

        // Get the module file name
        CharT buf[MAX_PATH];
        DWORD size = get_module_file_name(hSelfModule, buf, sizeof(buf) / sizeof(*buf));
        if (size == 0)
            BOOST_LOG_THROW_DESCR(system_error, "Could not get module file name");

        return std::basic_string< CharT >(buf, buf + size);
    }
typename default_filter_factory< CharT >::filter_type
default_filter_factory< CharT >::parse_argument(string_type const& name, string_type const& arg)
{
    filter_type filter;
    const bool full = bsc::parse(arg.c_str(), arg.c_str() + arg.size(),
        (
            bsc::strict_real_p[boost::bind(&this_type::BOOST_NESTED_TEMPLATE on_fp_argument< RelationT >, boost::cref(name), _1, boost::ref(filter))] |
            bsc::int_p[boost::bind(&this_type::BOOST_NESTED_TEMPLATE on_integral_argument< RelationT >, boost::cref(name), _1, boost::ref(filter))] |
            (+bsc::print_p)[boost::bind(&this_type::BOOST_NESTED_TEMPLATE on_string_argument< RelationT >, boost::cref(name), _1, _2, boost::ref(filter))]
        )
    ).full;

    if (!full || filter.empty())
        BOOST_LOG_THROW_DESCR(parse_error, "Failed to parse relation operand");

    return filter;
}
Beispiel #17
0
filter default_filter_factory< CharT >::on_custom_relation(attribute_name const& name, string_type const& rel, string_type const& arg)
{
    typedef log::aux::char_constants< char_type > constants;

    filter f;
    if (rel == constants::begins_with_keyword())
        on_string_argument< begins_with_fun >(name, f)(arg);
    else if (rel == constants::ends_with_keyword())
        on_string_argument< ends_with_fun >(name, f)(arg);
    else if (rel == constants::contains_keyword())
        on_string_argument< contains_fun >(name, f)(arg);
    else if (rel == constants::matches_keyword())
        on_regex_argument< matches_fun >(name, f)(arg);
    else
    {
        BOOST_LOG_THROW_DESCR(parse_error, "The custom attribute relation \"" + log::aux::to_narrow(rel) + "\" is not supported");
    }

    return boost::move(f);
}
typename default_filter_factory< CharT >::filter_type
default_filter_factory< CharT >::on_custom_relation(string_type const& name, string_type const& rel, string_type const& arg)
{
    typedef log::aux::char_constants< char_type > constants;
    if (rel == constants::begins_with_keyword())
        return filter_type(log::filters::attr< string_type >(name).begins_with(arg));
    else if (rel == constants::ends_with_keyword())
        return filter_type(log::filters::attr< string_type >(name).ends_with(arg));
    else if (rel == constants::contains_keyword())
        return filter_type(log::filters::attr< string_type >(name).contains(arg));
    else if (rel == constants::matches_keyword())
    {
        typedef xpressive::basic_regex< typename string_type::const_iterator > regex_t;
        regex_t rex = regex_t::compile(arg, regex_t::ECMAScript | regex_t::optimize);
        return filter_type(log::filters::attr< string_type >(name, std::nothrow).matches(rex));
    }
    else
    {
        BOOST_LOG_THROW_DESCR(parse_error, "The custom attribute relation is not supported");
    }
}
Beispiel #19
0
inline void interprocess_mutex::mark_waiting_and_try_lock(uint32_t& old_state)
{
    uint32_t new_state;
    do
    {
        uint32_t was_locked = (old_state & lock_flag_value);
        if (was_locked)
        {
            // Avoid integer overflows
            if (BOOST_UNLIKELY((old_state & waiter_count_mask) == waiter_count_mask))
                BOOST_LOG_THROW_DESCR(limitation_error, "Too many waiters on an interprocess mutex");

            new_state = old_state + 1u;
        }
        else
        {
            new_state = old_state | lock_flag_value;
        }
    }
    while (!m_shared_state->m_lock_state.compare_exchange_weak(old_state, new_state, boost::memory_order_acq_rel, boost::memory_order_relaxed));
}
Beispiel #20
0
    void init_event_log_registry(
        std::basic_string< CharT > const& log_name,
        std::basic_string< CharT > const& source_name,
        bool force,
        registry_params< CharT > const& params)
    {
        typedef std::basic_string< CharT > string_type;
        typedef registry_traits< CharT > registry;
        // Registry key name that contains log description
        string_type reg_key = registry::make_event_log_key(log_name, source_name);

        // First check the registry keys and values in read-only mode.
        // This allows to avoid UAC asking for elevated permissions to modify HKLM registry when no modification is actually needed.
        if (verify_event_log_registry(reg_key, force, params))
            return;

        // Create or open the key
        HKEY hkey = 0;
        DWORD disposition = 0;
        LSTATUS res = registry::create_key(
            HKEY_LOCAL_MACHINE,
            reg_key.c_str(),
            0,
            NULL,
            REG_OPTION_NON_VOLATILE,
            KEY_WRITE,
            NULL,
            &hkey,
            &disposition);
        if (res != ERROR_SUCCESS)
            BOOST_LOG_THROW_DESCR(system_error, "Could not create registry key for the event log");

        auto_hkey_close hkey_guard(hkey);

        if (disposition != REG_OPENED_EXISTING_KEY || force)
        {
            // Fill registry values
            if (!!params.event_message_file)
            {
                // Set the module file name that contains event resources
                string_type const& module_name = params.event_message_file.get();
                res = registry::set_value(
                    hkey,
                    registry::get_event_message_file_param_name(),
                    0,
                    REG_EXPAND_SZ,
                    reinterpret_cast< LPBYTE >(const_cast< CharT* >(module_name.c_str())),
                    static_cast< DWORD >((module_name.size() + 1) * sizeof(CharT)));
                if (res != ERROR_SUCCESS)
                {
                    BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
                        + log::aux::to_narrow(string_type(registry::get_event_message_file_param_name())));
                }
            }

            if (!!params.category_message_file)
            {
                // Set the module file name that contains event category resources
                string_type const& module_name = params.category_message_file.get();
                res = registry::set_value(
                    hkey,
                    registry::get_category_message_file_param_name(),
                    0,
                    REG_SZ,
                    reinterpret_cast< LPBYTE >(const_cast< CharT* >(module_name.c_str())),
                    static_cast< DWORD >((module_name.size() + 1) * sizeof(CharT)));
                if (res != ERROR_SUCCESS)
                {
                    BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
                        + log::aux::to_narrow(string_type(registry::get_category_message_file_param_name())));
                }
            }

            if (!!params.category_count)
            {
                // Set number of categories
                DWORD category_count = params.category_count.get();
                res = registry::set_value(
                    hkey,
                    registry::get_category_count_param_name(),
                    0,
                    REG_DWORD,
                    reinterpret_cast< LPBYTE >(&category_count),
                    static_cast< DWORD >(sizeof(category_count)));
                if (res != ERROR_SUCCESS)
                {
                    BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
                        + log::aux::to_narrow(string_type(registry::get_category_count_param_name())));
                }
            }

            if (!!params.types_supported)
            {
                // Set the supported event types
                DWORD event_types = params.types_supported.get();
                res = registry::set_value(
                    hkey,
                    registry::get_types_supported_param_name(),
                    0,
                    REG_DWORD,
                    reinterpret_cast< LPBYTE >(&event_types),
                    static_cast< DWORD >(sizeof(event_types)));
                if (res != ERROR_SUCCESS)
                {
                    BOOST_LOG_THROW_DESCR(system_error, "Could not create registry value "
                        + log::aux::to_narrow(string_type(registry::get_types_supported_param_name())));
                }
            }
        }
    }
Beispiel #21
0
//! Finds or creates a semaphore with zero counter
interprocess_condition_variable::semaphore_info* interprocess_condition_variable::get_unused_semaphore()
{
    // Be optimistic, check the current semaphore first
    if (m_current_semaphore && m_current_semaphore->m_semaphore.is_zero_count())
    {
        mark_unused(*m_current_semaphore);
        return m_current_semaphore;
    }

    const tick_count_clock::time_point now = tick_count_clock::now();

    semaphore_info_list::iterator it = m_semaphore_info_list.begin(), end = m_semaphore_info_list.end();
    while (it != end)
    {
        if (is_overflow_less(m_next_semaphore_id, it->m_id) || m_next_semaphore_id == it->m_id)
            m_next_semaphore_id = it->m_id + 1u;

        if (it->m_semaphore.is_zero_count())
        {
            semaphore_info& info = *it;
            mark_unused(info);
            return &info;
        }
        else if (it->check_non_zero_timeout(now))
        {
            // The semaphore is non-zero for too long. A blocked process must have crashed. Close it.
            m_semaphore_info_set.erase(m_semaphore_info_set.iterator_to(*it));
            m_semaphore_info_list.erase_and_dispose(it++, boost::checked_deleter< semaphore_info >());
        }
        else
        {
            ++it;
        }
    }

    // No semaphore found, create a new one
    for (uint32_t semaphore_id = m_next_semaphore_id, semaphore_id_end = semaphore_id - 1u; semaphore_id != semaphore_id_end; ++semaphore_id)
    {
        interprocess_semaphore sem;
        try
        {
            generate_semaphore_name(semaphore_id);
            sem.create_or_open(m_semaphore_name.c_str(), m_perms);
            if (!sem.is_zero_count())
                continue;
        }
        catch (...)
        {
            // Ignore errors, try the next one
            continue;
        }

        semaphore_info* p = NULL;
        semaphore_info_set::insert_commit_data insert_state;
        std::pair< semaphore_info_set::iterator, bool > res = m_semaphore_info_set.insert_check(semaphore_id, semaphore_info::order_by_id(), insert_state);
        if (res.second)
        {
            p = new semaphore_info(semaphore_id);
            p->m_semaphore.swap(sem);

            res.first = m_semaphore_info_set.insert_commit(*p, insert_state);
            m_semaphore_info_list.push_back(*p);
        }
        else
        {
            // Some of our currently open semaphores must have been released by another thread
            p = &*res.first;
            mark_unused(*p);
        }

        m_next_semaphore_id = semaphore_id + 1u;

        return p;
    }

    BOOST_LOG_THROW_DESCR(limitation_error, "Too many semaphores are actively used for an interprocess condition variable");
    BOOST_LOG_UNREACHABLE_RETURN(NULL);
}