`
tempsitegoogle
  • 浏览: 869036 次
文章分类
社区版块
存档分类
最新评论

OpenRTMFP/Cumulus Primer(20)Cumulus的一个线程启动 Bug

 
阅读更多

OpenRTMFP/Cumulus Primer(20)Cumulus的一个线程启动 Bug

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:June 25th, 2012

Cumulus 中的线程都是继承自 Startable,在其中封装 Poco::Thread 成员,使得一些有关线程的操作更方便。Startable 中的 start 函数如下:


void Startable::start() {
    if(!_stop) // if running
        return;
    ScopedLock<fastmutex> lock(_mutex);
    <span class="keyword" style="font-weight: bold; ">if</span>(_haveToJoin) {
        _thread.join();
        _haveToJoin=<span class="keyword" style="font-weight: bold; ">false</span>;
    }
    <span class="keyword" style="font-weight: bold; ">try</span> {
        DEBUG(<span class="string" style="color: rgb(136, 0, 0); ">"Try to start up a new thread inherited from Startable"</span>);
        _thread.start(_process);
        _haveToJoin = <span class="keyword" style="font-weight: bold; ">true</span>;
        ScopedLock<fastmutex> lock(_mutexStop);
        _stop=<span class="keyword" style="font-weight: bold; ">false</span>;
    } <span class="keyword" style="font-weight: bold; ">catch</span> (Poco::Exception&amp; ex) {
        ERROR(<span class="string" style="color: rgb(136, 0, 0); ">"Impossible to start the thread : %s"</span>,ex.displayText().c_str());
    }
}
</fastmutex></fastmutex>

这样一个类继承 Startable 的话,并启动时传入自己,则会调用到 Startable::start(),然后调用到该类自己的 run() 函数。一般来说这个函数会一个循环,以 SocketManager 为例:


void SocketManager::run() {
    … 
    while(running()) {
    …
    }
}

我们要看看这个 running() 是怎么回事,如下:


inline bool Startable::running() const {
    return !_stop;
}

很简单,就是通过 Startable::_stop 成员来判断是否还需要继续循环下去。那么这个 _stop 是什么时候被设置为 false 的呢?就是上面的 start(),这里存在的一个问题就是先 start 线程,再设置 _stop 为 false。


_thread.start(_process);
_stop=false;

而 start() 之后 run() 的时候就开始通过 running() 来判断 _stop 值了。所以你会在使用 Cumulus 时,发现有时候启动起来的线程个数不对。正常情况下应该有四个线程:

icon Resize

它们是:

  • 主线程
  • RTMFPServer 线程
  • MainSockets 线程
  • RTMFPManager 线程

而异常情况可能是 MainSockets 没有启动,甚至 MainSockets 和 RTMFPManager 都没有启动。

MainSockets 没有启动的情况,这时客户端是无法接入成功的。

icon Resize

MainSockets 和 RTMFPManager 都没有启动的情况 T.T

icon Resize

具体是哪个线程没有启动成功可以通过 GDB 查看。

解决办法就是将 _stop 的设置操作,在启动线程之前。不过要注意锁要同时移动,并且在产生异常时设置 _stop 值为 true。


void Startable::start() {
    if(!_stop) // if running
        return;
    ScopedLock<fastmutex> lock(_mutex);
    <span class="keyword" style="font-weight: bold; ">if</span>(_haveToJoin) {
        _thread.join();
        _haveToJoin=<span class="keyword" style="font-weight: bold; ">false</span>;
    }
    <span class="keyword" style="font-weight: bold; ">try</span> {
        DEBUG(<span class="string" style="color: rgb(136, 0, 0); ">"Try to start up a new thread inherited from Startable"</span>);
        {
            ScopedLock<fastmutex> lock(_mutexStop);
            _stop=<span class="keyword" style="font-weight: bold; ">false</span>;
        }
        _thread.start(_process);
        _haveToJoin = <span class="keyword" style="font-weight: bold; ">true</span>;
    } <span class="keyword" style="font-weight: bold; ">catch</span> (Poco::Exception&amp; ex) {
        {
            ScopedLock<fastmutex> lock(_mutexStop);
            _stop = <span class="keyword" style="font-weight: bold; ">true</span>; <span class="comment" style="color: rgb(136, 136, 136); ">// June 25th, 2012, Michael@YY</span>
        }
        ERROR(<span class="string" style="color: rgb(136, 0, 0); ">"Impossible to start the thread : %s"</span>,ex.displayText().c_str());
    }
}
</fastmutex></fastmutex></fastmutex>

-

转载请注明来自柳大·Poechant(钟超)的CSDN博客:Blog.CSDN.net/Poechant

-

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics