Mercurial > ublox > ublox8
changeset 99:5e4137c51146
ubx: fix race condition between commands processing and ack waiter
There was a chance of the device processing the command and returning
ACK/NAK before the thread sending the command got a chance to add itself to
the wait queue.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Wed, 13 Sep 2023 10:19:28 -0400 |
parents | 21ba18fc4e05 |
children | 2cb2ec63a098 |
files | ubx.c |
diffstat | 1 files changed, 17 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/ubx.c Wed Sep 13 10:11:17 2023 -0400 +++ b/ubx.c Wed Sep 13 10:19:28 2023 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2019-2021,2023 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -117,26 +117,6 @@ return 0; } -static bool __read_ubx_ack(int fd, enum ubx_msg_id id) -{ - struct ack_waiter waiter; - - CONDINIT(&waiter.cond); - waiter.finished = false; - waiter.id = id; - - MXLOCK(&ack_lock); - list_insert_tail(&ack_waiters, &waiter); - - while (!waiter.finished) - CONDWAIT(&waiter.cond, &ack_lock); - MXUNLOCK(&ack_lock); - - CONDDESTROY(&waiter.cond); - - return waiter.success; -} - void notify_ubx_ack(const uint8_t *data, size_t len, bool success) { struct ack_waiter *cur, *tmp; @@ -172,16 +152,29 @@ int send_ubx_with_ack(int fd, enum ubx_msg_id id, const void *data, size_t len) { - bool ack; + struct ack_waiter waiter; int ret; + CONDINIT(&waiter.cond); + waiter.finished = false; + waiter.id = id; + + MXLOCK(&ack_lock); + list_insert_tail(&ack_waiters, &waiter); + MXUNLOCK(&ack_lock); + ret = __send_ubx(fd, id, data, len); if (ret) return ret; - ack = __read_ubx_ack(fd, id); + MXLOCK(&ack_lock); + while (!waiter.finished) + CONDWAIT(&waiter.cond, &ack_lock); + MXUNLOCK(&ack_lock); - return ack ? 0 : -ENOTSUP; + CONDDESTROY(&waiter.cond); + + return waiter.success ? 0 : -ENOTSUP; } int enable_ubx_msg(int fd, enum ubx_msg_id id, int port, int rate)