Skip to content

Commit ce9335d

Browse files
committed
implement AsyncUDP teardown in destructor and review comments
1 parent a4617aa commit ce9335d

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

cores/portduino/AsyncUDP.cpp

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "AsyncUDP.h"
2+
#include "Utility.h"
23

34
void _asyncudp_async_cb(uv_async_t *handle) {
45
AsyncUDP *udp = (AsyncUDP *)handle->data;
@@ -38,9 +39,8 @@ bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl)
3839
if (_connected) {
3940
return false;
4041
}
41-
// FIXME: implement error handling rather than raising SIGSEGV
4242
if (uv_udp_init(&_loop, &_socket) < 0) {
43-
raise(SIGSEGV);
43+
portduinoError("FIXME: implement proper error handling; uv_udp_init failed");
4444
}
4545
_socket.data = this;
4646
// FIXME: don't do bytes → string → bytes IP conversion
@@ -49,23 +49,21 @@ bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl)
4949
snprintf(addr_str, maxIpLength, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
5050
addr_str[maxIpLength] = '\0';
5151
struct sockaddr uvAddr;
52-
if (uv_ip4_addr(addr_str, port, (struct sockaddr_in *)&uvAddr) < 0) {
53-
raise(SIGSEGV);
54-
}
52+
uv_ip4_addr(addr_str, port, (struct sockaddr_in *)&uvAddr);
5553
if (uv_udp_bind(&_socket, (const struct sockaddr *)&uvAddr, 0) < 0) {
56-
raise(SIGSEGV);
54+
portduinoError("FIXME: implement proper error handling; uv_udp_bind failed");
5755
}
5856
if (uv_udp_set_multicast_loop(&_socket, false) < 0) {
59-
raise(SIGSEGV);
57+
portduinoError("FIXME: implement proper error handling; uv_udp_set_multicast_loop failed");
6058
}
6159
if (uv_udp_set_multicast_ttl(&_socket, ttl) < 0) {
62-
raise(SIGSEGV);
60+
portduinoError("FIXME: implement proper error handling; uv_udp_set_multicast_ttl failed");
6361
}
6462
if (uv_udp_set_membership(&_socket, addr_str, NULL, UV_JOIN_GROUP) < 0) {
65-
raise(SIGSEGV);
63+
portduinoError("FIXME: implement proper error handling; uv_udp_set_membership failed");
6664
}
6765
if (uv_udp_recv_start(&_socket, _asyncudp_alloc_buffer_cb, _asyncudp_on_read_cb) < 0) {
68-
raise(SIGSEGV);
66+
portduinoError("FIXME: implement proper error handling; uv_udp_recv_start failed");
6967
}
7068

7169
_ioThread = std::thread([this](){
@@ -96,6 +94,16 @@ void AsyncUDP::_DO_NOT_CALL_async_cb() {
9694
_sendQueueMutex.lock();
9795
}
9896
_sendQueueMutex.unlock();
97+
if (_quit.load()) {
98+
uv_udp_recv_stop(&_socket);
99+
// FIXME: don't do bytes → string → bytes IP conversion
100+
int maxIpLength = 3*4+3; // 3 digits per octet, 4 octets, 3 dots
101+
char addr_str[maxIpLength+1]; // +1 for null terminator
102+
snprintf(addr_str, maxIpLength, "%d.%d.%d.%d", _listenIP[0], _listenIP[1], _listenIP[2], _listenIP[3]);
103+
addr_str[maxIpLength] = '\0';
104+
uv_udp_set_membership(&_socket, addr_str, NULL, UV_LEAVE_GROUP);
105+
uv_stop(&_loop);
106+
}
99107
};
100108

101109
void _asyncudp_send_cb(uv_udp_send_t *req, int status) {
@@ -111,15 +119,13 @@ void AsyncUDP::_doWrite(const uint8_t *data, size_t len, const IPAddress addr, u
111119

112120
// FIXME: implement error handling rather than raising SIGSEGV
113121
struct sockaddr uvAddr;
114-
if (uv_ip4_addr(addr_str, port, (struct sockaddr_in *)&uvAddr) < 0) {
115-
raise(SIGSEGV);
116-
}
122+
uv_ip4_addr(addr_str, port, (struct sockaddr_in *)&uvAddr);
117123

118124
uv_udp_send_t *req = (uv_udp_send_t *)malloc(sizeof(uv_udp_send_t));
119125
uv_buf_t msg;
120126
msg.base = (char *)data;
121127
msg.len = len;
122128
if (uv_udp_send(req, &_socket, &msg, 1, (const struct sockaddr *)&uvAddr, _asyncudp_send_cb) < 0) {
123-
raise(SIGSEGV);
129+
portduinoError("FIXME: implement proper error handling; uv_udp_send failed");
124130
}
125131
};

cores/portduino/AsyncUDP.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
#ifndef ESPASYNCUDP_H
44
#define ESPASYNCUDP_H
55

6-
#include <signal.h>
76
#include "IPAddress.h"
87
#include "Print.h"
98
#include <functional>
9+
#include <atomic>
1010
#include <mutex>
1111
#include <memory>
1212
#include <thread>
@@ -73,6 +73,7 @@ class AsyncUDP final
7373
// the queue is used because uv_udp_send is not threadsafe and uv_async can merge multiple calls into one callback
7474
std::vector<std::unique_ptr<asyncUDPSendTask>> _sendQueue;
7575

76+
std::atomic<bool> _quit;
7677
std::thread _ioThread;
7778

7879
bool _connected;
@@ -85,7 +86,10 @@ class AsyncUDP final
8586
public:
8687
AsyncUDP();
8788
~AsyncUDP() {
88-
raise(SIGSEGV); // FIXME: implement closing and teardown
89+
_quit.store(true);
90+
uv_async_send(&_async);
91+
_ioThread.join();
92+
uv_loop_close(&_loop);
8993
}
9094

9195
void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg=NULL) {

0 commit comments

Comments
 (0)