1

ワーク キューを使用してタスクを実行するプログラムがあり、デーモンとして実行することになっています。次のコードを使用してこれを達成していました。

bool seedDaemon() {
        using namespace std;
        int childpid = 0;
        pid_t pid = 0;
        if( ( childpid = fork() ) < 0 ) {
                return false;
        }
        else if( childpid > 0 ){
                exit(0);
        }
        setsid();
        umask(0);
        std::cout<< "[OK]\n";
        close( fileno(stderr) );
        close( fileno(stdout) );
        close( STDIN_FILENO );
        return true;
}

これにより、元のプロセスが閉じられ、別のプロセスが開始されます。ただし、これにより、タスクを実行するために作成したスレッドがフォーク後に再び表示されないという問題が発生しました。ワーク キューはグローバルにインスタンス化されます。他のすべての値とメモリ アドレスは子に正しくコピーされますが、スレッドはコピーされません。

参考までに、プールクラスは次のとおりです。

プール.h:

#ifndef __POOL_H
#define __POOL_H
class tpool {
        public:
                tpool( std::size_t tpool_size );
                ~tpool();
                template< typename Task >
                void run_task( Task task ){ // add item to the queue
                        io_service_.post( boost::bind( &tpool::wrap_task, this,
                                boost::function< void() > ( task ) ) );
                }
        private:
                boost::asio::io_service io_service_;
                boost::asio::io_service::work work_;
                boost::thread_group threads_;
                boost::mutex mutex_;
                void wrap_task( boost::function< void() > task );
};

extern tpool dbpool; 
#endif

プール.cpp:

#include <boost/asio/io_service.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include "pool.h"
tpool::tpool( std::size_t tpool_size ) : work_( io_service_ ), available_( tpool_size ) {
    for ( std::size_t i = 0; i < tpool_size; ++i ){
        threads_.create_thread( boost::bind( &boost::asio::io_service::run, &io_service_ ) );
    }
}
tpool::~tpool() {
    io_service_.stop();
    try {
        threads_.join_all();
    }
    catch( ... ) {}
}
void tpool::wrap_task( boost::function< void() > task ) {
    // run the supplied task
    try {
        task();
    } // suppress exceptions
    catch( ... ) {
    }
    boost::unique_lock< boost::mutex > lock( mutex_ );
    ++available_;
}
tpool dbpool( 50 );

では、どうすればこれを解決できますか?

4

2 に答える 2

5

最も簡単な方法は、グローバルを使用しないことです。それらは、あなたが発見した理由 (およびそれ以上) とまったく同じ理由で悪いです。

手っ取り早い回避策として、

extern tpool dbpool();  // function!

cpp では次のように実装されています。

tpool& dbpool() {
    static tpool the_instance; // only initialized on first call
    return the_instance;
}

そうすれば、呼び出さない限りdbpool()初期化されません。(関数 local static の初期化は、c++11 以降、スレッドセーフです)。

注:tpoolグローバル名前空間のような名前を持つことは、実際には C++ のコード臭であるため、いくつかの名前空間を追加してください。

于 2014-09-26T12:13:36.160 に答える
2

スレッドが fork() に耐えられないことを知っていますよね? fork() の後に呼び出すメソッドにスレッド割り当てを入れても害はありません。ご存知のように、コンストラクターは....ものを作るのに最適な場所ではない場合があります。もちろん、グローバルを回避して、フォークがうまくいくまで構築を遅らせることができます。

おそらく、制御端末からデーモンを切り離すことも検討する必要があります。

于 2014-09-26T13:02:04.140 に答える