Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使助推asio叉子安全 我使用Boost ASIO构建了一个C++库。该库需要线程安全和fork安全。 它有服务调度程序线程,它调用io\u service::run()。为了支持fork安全,我注册了pre\u fork、post\u fork\u parent和post\u fork\u child处理程序。pre\u fork()_C++_Boost_Fork_Boost Asio - Fatal编程技术网

如何使助推asio叉子安全 我使用Boost ASIO构建了一个C++库。该库需要线程安全和fork安全。 它有服务调度程序线程,它调用io\u service::run()。为了支持fork安全,我注册了pre\u fork、post\u fork\u parent和post\u fork\u child处理程序。pre\u fork()

如何使助推asio叉子安全 我使用Boost ASIO构建了一个C++库。该库需要线程安全和fork安全。 它有服务调度程序线程,它调用io\u service::run()。为了支持fork安全,我注册了pre\u fork、post\u fork\u parent和post\u fork\u child处理程序。pre\u fork(),c++,boost,fork,boost-asio,C++,Boost,Fork,Boost Asio,我在中遇到的问题是,当fork()发生时,服务调度程序线程可能正在执行某些操作,并且可能已经锁定了io\u服务对象的数据成员。因此,当我们调用\u io\u服务时,子进程看到它们处于相同的状态,并且在post\u fork\u child()中(boost::asio::io_service::fork_child)它试图获取同一对象上的锁,因此被无限期阻止(因为child中没有线程来释放解锁) 我在子进程中看到的堆栈跟踪被阻止,它是- fffffd7ffed07577 lwp_park (0,

我在中遇到的问题是,当
fork()
发生时,服务调度程序线程可能正在执行某些操作,并且可能已经锁定了
io\u服务
对象的数据成员。因此,当我们调用
\u io\u服务时,子进程看到它们处于相同的状态,并且在post\u fork\u child()中(boost::asio::io_service::fork_child)
它试图获取同一对象上的锁,因此被无限期阻止(因为child中没有线程来释放解锁)

我在子进程中看到的堆栈跟踪被阻止,它是-

fffffd7ffed07577 lwp_park (0, 0, 0) 
fffffd7ffecffc18 mutex_lock_internal () + 378 
fffffd7ffecfffb2 mutex_lock_impl () + 112 
fffffd7ffed0007b mutex_lock () + b 
fffffd7fff26419d __1cFboostEasioGdetailLscoped_lock4n0CLposix_mutex__2t5B6Mrn0D__v_ () + 1d 
fffffd7fff2866a2 __1cFboostEasioGdetailQdev_poll_reactorMfork_service6Mn0BKio_serviceKfork_event__v_ () + 32 
fffffd7fff278527 __1cFboostEasioGdetailQservice_registryLnotify_fork6Mn0BKio_serviceKfork_event__v_ () + 107 
fffffd7fff27531c __1cDdesGtunnelQServiceSchedulerPpost_fork_child6M_v_ () + 1c 
fffffd7fff29de24 post_fork_child () + 84 
fffffd7ffec92188 _postfork_child_handler () + 38 
fffffd7ffecf917d fork () + 12d 
fffffd7ffec172d5 fork () + 45 
fffffd7ffef94309 fork () + 9 
000000000043299d main () + 67d 
0000000000424b2c ???????? () 
显然,当导致问题的fork发生时,服务调度器线程中的“dev_poll_reactor”被锁定(因为它似乎正在调度一些挂起的事件)

< P> >我想解决这个问题,我需要确保服务调度器线程不在发生叉的任何处理的中间,并且保证在Pyl For()中调用<代码> IoService。但是这听起来不是一个好的解决方案。你能告诉我什么是使库叉安全的正确方法吗

代码片段如下所示

/** 
 * Combines Boost.ASIO with a thread for scheduling. 
 */ 
class ServiceScheduler : private boost::noncopyable 
{ 
public : 
    /// The actual thread used to perform work. 
    boost::shared_ptr<boost::thread>             _service_thread; 

    /// Service used to manage async I/O events 
    boost::asio::io_service                      _io_service; 

    /// Work object to block the ioservice thread. 
    std::auto_ptr<boost::asio::io_service::work> _work; 
    ... 
}; 

/** 
 * CTOR 
 */ 
ServiceScheduler::ServiceScheduler() 
    : _io_service(), 
      _work(std::auto_ptr<boost::asio::io_service::work>( 
              new boost::asio::io_service::work(_io_service))), 
      _is_running(false) 
{ 
} 

/** 
 * Starts a thread to run async I/O service to process the scheduled work. 
 */ 
void ServiceScheduler::start() 
{ 
    ScopedLock scheduler_lock(_mutex); 
    if (!_is_running) { 
        _is_running = true; 
        _service_thread = boost::shared_ptr<boost::thread>( 
                new boost::thread(boost::bind( 
                        &ServiceScheduler::processServiceWork, this))); 
    } 
} 

/** 
 *  Processes work passed to the ASIO service and handles uncaught 
 *  exceptions 
 */ 
void ServiceScheduler::processServiceWork() 
{ 
    try { 
        _io_service.run(); 
    } 
    catch (...) { 
    } 
} 

/** 
 * Pre-fork handler 
 */ 
void ServiceScheduler::pre_fork() 
{ 
    _io_service.notify_fork(boost::asio::io_service::fork_prepare); 
} 

/** 
 * Post-fork parent handler 
 */ 
void ServiceScheduler::post_fork_parent() 
{ 
    _io_service.notify_fork(boost::asio::io_service::fork_parent); 
} 

/**
 * Post-fork child handler 
 */ 
void ServiceScheduler::post_fork_child() 
{ 
    _io_service.notify_fork(boost::asio::io_service::fork_child);
}
/**
*将Boost.ASIO与用于调度的线程相结合。
*/ 
类ServiceScheduler:私有boost::不可复制
{ 
公众:
///用于执行工作的实际线程。
boost::共享\u ptr\u服务\u线程;
///用于管理异步I/O事件的服务
boost::asio::io_服务_io_服务;
///用于阻止ioservice线程的工作对象。
标准:自动ptr工作;
... 
}; 
/** 
*执行器
*/ 
ServiceScheduler::ServiceScheduler()
:_io_service(),
_工作(标准::自动测试(
新的boost::asio::io_服务::work(_io_服务)),
__正在运行(错误)
{ 
} 
/** 
*启动线程以运行异步I/O服务来处理计划的工作。
*/ 
void ServiceScheduler::start()
{ 
ScopedLock调度程序锁定(互斥);
如果(!\u正在运行){
_正在运行=正确;
_服务线程=boost::共享线程(
新的boost::线程(boost::bind(
&ServiceScheduler::processServiceWork,这是);
} 
} 
/** 
*处理传递给ASIO服务的工作并处理未完成的工作
*例外情况
*/ 
void ServiceScheduler::processServiceWork()
{ 
试试{
_io_service.run();
} 
捕获(…){
} 
} 
/** 
*前叉式装卸机
*/ 
void ServiceScheduler::pre_fork()
{ 
_io_服务。通知_fork(boost::asio::io_服务::fork\u prepare);
} 
/** 
*后置叉父处理程序
*/ 
void ServiceScheduler::post_fork_parent()
{ 
_io_服务。通知_分叉(boost::asio::io_服务::分叉父级);
} 
/**
*后叉子处理程序
*/ 
void ServiceScheduler::post_fork_child()
{ 
_io_服务。通知_分支(boost::asio::io_服务::分支子级);
}

我正在使用boost 1.47并在Solaris i386上运行应用程序。库和应用程序是使用studio-12.0构建的。

asio代码指定当io服务代码中有任何代码时,
notify\u fork()
不起作用

当任何其他io_服务函数运行时,不得调用此函数,或 与io_服务关联的I/O对象上的任何函数都是 在另一个线程中调用。但是,从 在完成处理程序中,如果没有其他线程访问 io_服务

这似乎包括
run
或与库关联的任何IO。我认为您的预处理应该重置一个工作项

e、 g.来自

boost::asio::io_服务io_服务;
自动检查工作(
新的boost::asio::io_服务::工作(io_服务));
...
pre_fork(){
work.reset();//允许run()退出。
//检查运行已完成。。。
io_服务。通知_分叉(…);
}
仍然需要小心

  • 确保在
    post\u fork()
    完成之前未调用
    run()
  • 确保为下一次运行创建了新的
    work
    对象
  • 正确同步以确保检测到
    运行
    终止

  • 您可以使用io_服务::run_one检查fork是否已计划/io_服务是否仍在运行。当发生fork时,可以向io_服务添加一些工作以使线程唤醒。线程检查运行条件并立即停止。在fork发生后,父级或子级都可以重新启动worker t线程

    /**
     * Combines Boost.ASIO with a thread for scheduling.
     */
    class ServiceScheduler : private boost::noncopyable
    {
    public :
        /// The actual thread used to perform work.
        boost::shared_ptr<boost::thread>             _service_thread;
    
        /// Service used to manage async I/O events
        boost::asio::io_service                      _io_service;
    
        /// Work object to block the ioservice thread.
        std::auto_ptr<boost::asio::io_service::work> _work;
        ServiceScheduler();
        void start();
        void pre_fork();
    private:
        void processServiceWork();
        void post_fork_parent();
        void post_fork_child();
        std::atomic<bool> _is_running;
    };
    
    /**
     * CTOR
     */
    ServiceScheduler::ServiceScheduler()
        : _io_service(),
          _work(std::auto_ptr<boost::asio::io_service::work>(
                  new boost::asio::io_service::work(_io_service))),
          _is_running(false)
    {
    }
    
    /**
     * Starts a thread to run async I/O service to process the scheduled work.
     */
    void ServiceScheduler::start()
    {
        if(!_is_running) {
            _service_thread = boost::shared_ptr<boost::thread>(
                    new boost::thread(boost::bind(
                            &ServiceScheduler::processServiceWork, this)));
        }
    }
    
    /**
     *  Processes work passed to the ASIO service and handles uncaught
     *  exceptions
     */
    void ServiceScheduler::processServiceWork()
    {
        try {
            while(_is_running) {
                _io_service.run_one();
            }
         }
        catch (...) {
        }
        _is_running = false;
    }
    
    /**
     * Pre-fork handler
     */
    void ServiceScheduler::pre_fork()
    {
        _is_running = false;
        _io_service.post([](){ /*no_op*/});
        _service_thread->join();
        _service_thread.reset();
        _io_service.notify_fork(boost::asio::io_service::fork_prepare);
    }
    
    /**
     * Post-fork parent handler
     */
    void ServiceScheduler::post_fork_parent()
    {
        start();
        _io_service.notify_fork(boost::asio::io_service::fork_parent);
    }
    
    /**
     * Post-fork child handler
     */
    void ServiceScheduler::post_fork_child()
    {
        _io_service.notify_fork(boost::asio::io_service::fork_child);
    }
    
    /**
    *将Boost.ASIO与用于调度的线程相结合。
    */
    类ServiceScheduler:私有boost::不可复制
    {
    公众:
    ///用于执行工作的实际线程。
    boost::共享\u ptr\u服务\u线程;
    ///用于管理异步I/O事件的服务
    boost::asio::io_服务_io_服务;
    ///用于阻止ioservice线程的工作对象。
    标准:自动ptr工作;
    ServiceScheduler();
    void start();
    void pre_fork();
    私人:
    void processServiceWork();
    void post_fork_parent();
    void post_fork_child();
    std::atomic正在运行;
    };
    /**
    *执行器
    */
    ServiceScheduler::ServiceScheduler()
    :_io_service(),
    _工作(标准::自动检查)(
    新的boost::asio::io_服务::work(_io_服务)),
    _你是鲁尼吗
    
    /**
     * Combines Boost.ASIO with a thread for scheduling.
     */
    class ServiceScheduler : private boost::noncopyable
    {
    public :
        /// The actual thread used to perform work.
        boost::shared_ptr<boost::thread>             _service_thread;
    
        /// Service used to manage async I/O events
        boost::asio::io_service                      _io_service;
    
        /// Work object to block the ioservice thread.
        std::auto_ptr<boost::asio::io_service::work> _work;
        ServiceScheduler();
        void start();
        void pre_fork();
    private:
        void processServiceWork();
        void post_fork_parent();
        void post_fork_child();
        std::atomic<bool> _is_running;
    };
    
    /**
     * CTOR
     */
    ServiceScheduler::ServiceScheduler()
        : _io_service(),
          _work(std::auto_ptr<boost::asio::io_service::work>(
                  new boost::asio::io_service::work(_io_service))),
          _is_running(false)
    {
    }
    
    /**
     * Starts a thread to run async I/O service to process the scheduled work.
     */
    void ServiceScheduler::start()
    {
        if(!_is_running) {
            _service_thread = boost::shared_ptr<boost::thread>(
                    new boost::thread(boost::bind(
                            &ServiceScheduler::processServiceWork, this)));
        }
    }
    
    /**
     *  Processes work passed to the ASIO service and handles uncaught
     *  exceptions
     */
    void ServiceScheduler::processServiceWork()
    {
        try {
            while(_is_running) {
                _io_service.run_one();
            }
         }
        catch (...) {
        }
        _is_running = false;
    }
    
    /**
     * Pre-fork handler
     */
    void ServiceScheduler::pre_fork()
    {
        _is_running = false;
        _io_service.post([](){ /*no_op*/});
        _service_thread->join();
        _service_thread.reset();
        _io_service.notify_fork(boost::asio::io_service::fork_prepare);
    }
    
    /**
     * Post-fork parent handler
     */
    void ServiceScheduler::post_fork_parent()
    {
        start();
        _io_service.notify_fork(boost::asio::io_service::fork_parent);
    }
    
    /**
     * Post-fork child handler
     */
    void ServiceScheduler::post_fork_child()
    {
        _io_service.notify_fork(boost::asio::io_service::fork_child);
    }