Hi,

I've never seen anything like that before and, as ou say, no real work ha sbeen don in that are since 1.0.2 so I doubt it's a fixed bug.

Although libqb claims thread-safety I wouldn't rule out a threading bug with you adding timers from another thread. Looking at the test suite there is actually very little testing of libqbs thread-safety so that's where I would start looking for a start.

I'll have a play with it today, but you are able to come up with a reproducer for us that would be very helpful.

Chrissie

On 25/01/2021 05:29, Miranda, Russel wrote:
Hello ClusterLabs Developers,

I'm a developer working on an application that is using libqb (1.0.2) for its 
main event loop, and after running for a few hours, I'm encountering this 
assertion failure:

loop_timerlist.c:67: make_job_from_tmo: Assertion `t->state == 
QB_POLL_ENTRY_ACTIVE' failed.

The assertion causes a SIGABRT, and generates a core file. The stack trace is 
at the point of the failure is:

#0  0x00007ff3c76dd207 in raise () from /lib64/libc.so.6
#1  0x00007ff3c76de8f8 in abort () from /lib64/libc.so.6
#2  0x00007ff3c76d6026 in __assert_fail_base () from /lib64/libc.so.6
#3  0x00007ff3c76d60d2 in __assert_fail () from /lib64/libc.so.6
#4  0x00007ff3ca1c828d in make_job_from_tmo (data=0x5460250) at 
loop_timerlist.c:67
#5  0x00007ff3ca1c815b in timerlist_expire (timerlist=0x5dffe98) at 
../include/tlist.h:210
#6  expire_the_timers (s=0x5dffe80, ms_timeout=<optimized out>) at 
loop_timerlist.c:78
#7  0x00007ff3ca1c6acc in qb_loop_run (lp=<optimized out>) at loop.c:175 ...

Going back up to the point of the assertion (make_job_from_tmo), here is what the 
"data" parameter looks like:

(gdb) p *((struct qb_loop_timer*)data)
$1 = {item = {list = {next = 0x5460250, prev = 0x5460250}, source = 0x5dffe80, 
user_data = 0x7ff3c9144f60 <sessions+6240>, type = QB_LOOP_FD},
   dispatch_fn = 0xac8b00 <sessionTimeoutHandler(void*)>, p = QB_LOOP_MED, 
timerlist_handle = 0x0, state = QB_POLL_ENTRY_EMPTY, check = 978999470, install_pos = 
11}

Indeed, as the assertion indicates, t->state is QB_POLL_ENTRY_EMPTY when the 
assertion fails.

The timer that appears to have expired was added a few seconds earlier at the 
point when a message was sent (via socket) to an external entity. Typically, 
when that entity responds, the timer is stopped (via qb_loop_timer_del) to 
prevent expiration. If timer expiration occurs before the response is received, 
the registered dispatch function is called to handle failure of the external 
entity to respond.

That this timer would expire and call the dispatch_fn 
(sessionTimeoutHandler(void*)) passing in the value of user_data (0x7ff3c9144f60) 
at this point in the operation of the program is entirely plausible / expected, 
and I have validated that user_data points to a valid object of the appropriate 
type as well - so all of the caller-settable data looks correct to me in the timer 
entry. While I cannot completely exclude the possibility that something stepped on 
the t->state value, it seems unlikely that it would have affected only that one 
object property in the timer entry.

It appears to me that the timer has expired, but the timer list entry has the wrong 
state. I'm confused to how that might occur. I've been searching through the API 
documentation and online through forums, and I can't find anyone else reporting this 
particular assertion failure within "make_job_from_tmo", or even suggesting 
what we might be doing wrong to cause it. Has anyone seen this before?

Some additional notes:

* There is another thread active that can call qb_loop_timer_add to add a timer 
to the main event loop (it is not the timer that has expired here), but it 
could have been adding a timer at the same time this timer expired.
   My understanding is that (excluding the IPC calls), libqb is thread-safe, so 
it should be safe to call the qb_loop_timer_add() API from another thread. 
qb_loop_timer_add() is the only libqb API called from the other thread.
* In some cases we are adding timers that expire immediately (that is, with a 
delay as short as 0ns). That is not the case with this particular timer, it has 
a delay that is several seconds long.
   The qb_loop_timer_add() API doesn't indicate a minimum for the delay, so I 
am not aware of this being an incorrect usage - though we could probably switch 
to calling the qb_loop_job_add API instead if that is an incorrect use of the 
API.

None of the libqb releases since 1.0.2 appear to have any changes introduced 
specifically to address a problem like this - though I do see there were some 
minor updates made to the loop_timerlist.c code to silence warnings. If there 
is a known problem in this area in 1.0.2, I will try see how hard it is going 
to be to step up to the newer version.

I'm hoping someone has seen this problem before, or can suggest something that 
we might be doing wrong in the use of the API that could lead to this state.

Sincere thanks for any suggestions,

Russ

_______________________________________________
Manage your subscription:
https://lists.clusterlabs.org/mailman/listinfo/developers

ClusterLabs home: https://www.clusterlabs.org/


_______________________________________________
Manage your subscription:
https://lists.clusterlabs.org/mailman/listinfo/developers

ClusterLabs home: https://www.clusterlabs.org/

Reply via email to