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)