设为首页 加入收藏

TOP

Linux wait返回及timer_create问题解决(一)
2018-08-16 09:31:23 】 浏览:954
Tags:Linux wait 返回 timer_create 问题 解决

前言
前段时间查一个问题,发现应用层在使用wait函数时,在没有等到信号的情况下,wait函数返回了,并且返回值为0,没有超时及异常提示,不符合常理,跟进后发现,虽然c库代码编写不够严谨,但根源是应用层代码对timer_create的不当使用,引入了隐患。在这做一个分析,作为以后分析同类问题的参考。


一、 wait函数不合理返回问题
如下面代码,在postAndWait函数中,先把task queue进处理队列,然后调用wait等待task处理完成发送信号,接着在run函数中运行task及发送信号,当wait函数收到信号后,正常返回,这为正常的运行流程。但发现有时出现了在run中,task还没运行,也没有发送信号,wait函数就已经返回,并且返回值为0(success)。


frameworks\base\libs\hwui\renderthread\ RenderProxy.cpp


void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
    void* retval;
    task->setReturnPtr(&retval);
    SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
    AutoMutex _lock(mSyncMutex);
    mRenderThread.queue(&syncTask);    // queue task
    mSyncCondition.wait(mSyncMutex);  // 等待task运行完成发送信号
    return retval;   
// 若在task还没运行,wait就返回,task被释放,task运行线程不知道task被释放,一到task运行就出问题
}


frameworks\base\libs\hwui\renderthread\ RenderTask.cpp


void SignalingRenderTask::run() {
    mTask->run();        // task的运行
    mLock->lock();
    mSignal->signal();      // 发送信号给wait
    mLock->unlock();
}


二、wait不合理返回分析
跟进内核代码发现,当wait函数在等待时,wait所在的线程被挂起,正常情况下,当task的运行线程给wait所在的线程发送信号后,wait所在的线程被设置为可运行状态,等待系统调度运行并正常返回,wait函数调用路径及返回如下,调用路径如绿色标示的,返回点如紫色标示。(发送信号流程的代码位置与wait流程代码处于相同文件中,可自行跟踪)
system\core\include\utils\ Condition.h


inline status_t Condition::wait(Mutex& mutex) {
    return -pthread_cond_wait(&mCond, &mutex.mMutex);
}


bionic\libc\bionic\ Pthread_cond.cpp


int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) {
  return __pthread_cond_timedwait(cond, mutex, NULL,  COND_GET_CLOCK(cond->value));
}


bionic\libc\bionic\ Pthread_cond.cpp


__LIBC_HIDDEN__
int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime, clockid_t clock) {
  timespec ts;
  timespec* tsp;


  if (abstime != NULL) {        // 没有设置超时时间,不走这里
    if (__timespec_from_absolute(&ts, abstime, clock) < 0) {
      return ETIMEDOUT;
    }
    tsp = &ts;
  } else {
    tsp = NULL;
  }


  return __pthread_cond_timedwait_relative(cond, mutex, tsp);
}


bionic\libc\bionic\ Pthread_cond.cpp


__LIBC_HIDDEN__
int __pthread_cond_timedwait_relative(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* reltime) {
  int old_value = cond->value;


  pthread_mutex_unlock(mutex);
  int status = __futex_wait_ex(&cond->value, COND_IS_SHARED(cond->value), old_value, reltime);
  pthread_mutex_lock(mutex);


  if (status == -ETIMEDOUT) {
    return ETIMEDOUT;
  }


  return 0;
}
bionic\libc\private\ Bionic_futex.h
static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) {
  return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout);
}


bionic\libc\private\ Bionic_futex.h


static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) {
  // Our generated syscall assembler sets errno, but our caller

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Linux下sdio设备扫描过程 下一篇Python装饰器入门笔记

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目