chThdWait() may fail when registry enabled Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
Thargon
Posts: 107
Joined: Wed Feb 04, 2015 5:03 pm
Location: CITEC, Bielefeld University, germany
Has thanked: 11 times
Been thanked: 17 times

chThdWait() may fail when registry enabled  Topic is solved

Postby Thargon » Thu Dec 12, 2019 2:12 pm

I just encountered an issue with the chThdWait() function when I enable the registry module. As a disclaimer, I am not quite sure whether this is actually a bug or intended behaviour.

The scenario that causes my issue is quite simple: Thread A terminates thread B by calling chThdTerminate(&B) and waits for the thread to exit by calling chThdWait(&B). So far, everything works fine and thread A moves on. Eventually it calls chThdWait(&B) a second time later on, but this time that call fails due to triggered debug checks.

After a brief investigation, the cause of this is pretty clear. Let's have a look at the code:

Code: Select all

msg_t chThdWait(thread_t *tp) {
  msg_t msg;
 
  chDbgCheck(tp != NULL);
 
  chSysLock();
  chDbgAssert(tp != currp, "waiting self");
#if CH_CFG_USE_REGISTRY == TRUE
  chDbgAssert(tp->refs > (trefs_t)0, "no references");
#endif
 
  if (tp->state != CH_STATE_FINAL) {
    list_insert(currp, &tp->waiting);
    chSchGoSleepS(CH_STATE_WTEXIT);
  }
  msg = tp->u.exitcode;
  chSysUnlock();
 
#if CH_CFG_USE_REGISTRY == TRUE
  /* Releasing a reference to the thread.*/
  chThdRelease(tp);
#endif
 
  return msg;
}
Let's assume the value of tp->refs is 1 at first. The according assertion is fine for now and at the end of the function the thread is 'released', which decrements the tp->refs value by 1 to the new value of 0. However, when the function is called again of the same thread, the call of chDbgAssert(tp->refs > 0) obviously fails.

In case this is an actual bug, I'd propose the following fix:

Code: Select all

msg_t chThdWait(thread_t *tp) {
  ...
#if CH_CFG_USE_REGISTRY == TRUE
  chDbgAssert(tp->state == CH_STATE_FINAL || tp->refs > (trefs_t)0, "no references");
#endif
  ...
#if CH_CFG_USE_REGISTRY == TRUE
  /* Releasing a reference to the thread.*/
  if (tp->refs > 0) {
    chThdRelease(tp);
  }
#endif
  ...
}

Thomas

User avatar
Giovanni
Site Admin
Posts: 12742
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 693 times
Been thanked: 572 times
Contact:

Re: chThdWait() may fail when registry enabled

Postby Giovanni » Fri Dec 13, 2019 8:25 am

Hi,

This is the intended behavior, if you call chThdWait() you are losing your "reference" to the thread, further calls using that thread pointer are illegal.

If you need to keep a reference after calling chThdWait() then you need to get another reference by calling chThdAddRef().

Giovanni


Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 2 guests