2

1つのスレッドがすでにタイムアウトハンドラー内にあるときに、コンテキストスイッチ中に期限タイマーが破棄されるとどうなりますか?

たとえば、TimerCallbackの実行中に、別のスレッドへのコンテキストスイッチがScheduledCommandを削除した場合はどうなりますか?

ScheduledCommand::ScheduledCommand(
        const boost::shared_ptr<CommandInterface> command,
        const boost::posix_time::time_duration timeTillExecution):
    mTimer(TheCommandTimerThread::instance()->IoService(), timeTillExecution),
    mCommand(command)
{
    mTimer.async_wait(boost::bind(&ScheduledCommand::TimerCallback,
                                  this,
                                  boost::asio::placeholders::error));
}

ScheduledCommand::~ScheduledCommand()
{
    Cancel();
}

void ScheduledCommand::TimerCallback(const boost::system::error_code& error)
{
    if (!error)
    {
        assert(mCommand);
        mCommand->Execute();
    }
}

上記のコードでは、mCommand-> Execute()でセグメンテーション違反が発生しました。GDB分析は、mCommandが無効であることを示しました。おそらく別のスレッドから削除されました。ありがとう。

編集:

次の変更でこの問題が修正されないのはなぜですか?

ScheduledCommand::Cancel()
{
    if (mTimer.cancel() == 0) 
    { 
        mTimer.wait() 
    } 
}
4

1 に答える 1

1

マルチスレッド環境で、あるスレッドでオブジェクトを削除し、それを別のスレッドで使用すると、ご覧のようにクラッシュする可能性があります。

boost::asio を使用する場合、タイマーをキャンセルしても、オブジェクトを安全に破棄する前に、ハンドラーを実行させる必要があります (操作がキャンセルされたというエラーが発生します)。セットアップの残りの部分に応じて、いくつかのアプローチがあります。同期プリミティブを手動で使用する、 を使用しboost::asio::strandて一部の対話を 1 つのスレッドに制限する、または を使用boost::shared_ptrして主要なオブジェクトが参照されなくなるまで確実に実行できるようにする。

より多くの情報がなければ、最良の選択肢を伝えることは困難です.

于 2012-10-24T21:26:17.190 に答える