mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
sock/async: cancel sock async events when closing the socket
This commit is contained in:
parent
775f59623d
commit
0f25aecceb
@ -30,6 +30,10 @@
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sock_internal.h"
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
#include "net/sock/async/event.h"
|
||||
#endif
|
||||
|
||||
int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local,
|
||||
const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags)
|
||||
{
|
||||
@ -60,6 +64,9 @@ void sock_ip_close(sock_ip_t *sock)
|
||||
netconn_delete(sock->base.conn);
|
||||
sock->base.conn = NULL;
|
||||
}
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_ip_get_async_ctx(sock));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *ep)
|
||||
|
||||
@ -24,6 +24,10 @@
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
#include "net/sock/async/event.h"
|
||||
#endif
|
||||
|
||||
static inline void _tcp_sock_init(sock_tcp_t *sock, struct netconn *conn,
|
||||
sock_tcp_queue_t *queue)
|
||||
{
|
||||
@ -125,6 +129,10 @@ void sock_tcp_disconnect(sock_tcp_t *sock)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_tcp_get_async_ctx(sock));
|
||||
#endif
|
||||
|
||||
mutex_unlock(&sock->mutex);
|
||||
memset(&sock->mutex, 0, sizeof(mutex_t));
|
||||
}
|
||||
|
||||
@ -27,6 +27,10 @@
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
#include "net/sock/async/event.h"
|
||||
#endif
|
||||
|
||||
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
|
||||
const sock_udp_ep_t *remote, uint16_t flags)
|
||||
{
|
||||
@ -56,6 +60,9 @@ void sock_udp_close(sock_udp_t *sock)
|
||||
netconn_delete(sock->base.conn);
|
||||
sock->base.conn = NULL;
|
||||
}
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_udp_get_async_ctx(sock));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep)
|
||||
|
||||
@ -349,6 +349,9 @@ void sock_udp_close(sock_udp_t *sock)
|
||||
LL_DELETE(_udp_socket_list, sock);
|
||||
mutex_unlock(&_sock_list_lock);
|
||||
sock->next = NULL;
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_udp_get_async_ctx(udp));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -939,6 +939,9 @@ ssize_t sock_dtls_recv_buf_aux(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
||||
void sock_dtls_close(sock_dtls_t *sock)
|
||||
{
|
||||
dtls_free_context(sock->dtls_ctx);
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_dtls_get_async_ctx(sock));
|
||||
#endif
|
||||
}
|
||||
|
||||
void sock_dtls_init(void)
|
||||
|
||||
@ -25,6 +25,13 @@
|
||||
* For the following example [`sock_udp`](@ref net_sock_udp) is used. It is
|
||||
* however easily adaptable for other `sock` types:
|
||||
*
|
||||
* @warning An async socket may only be closed from the same thread that
|
||||
* processes the queue. This is because there is no way to prevent the
|
||||
* networking subsystem from posting socket events other than calling
|
||||
* sock_*_close(), which would then race against these events. If
|
||||
* unsure, use sock_*_event_close(), which will close the socket on
|
||||
* the correct thread.
|
||||
*
|
||||
* ### An asynchronous UDP Echo server using the event API
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||
@ -191,6 +198,15 @@ extern "C" {
|
||||
*/
|
||||
void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
|
||||
sock_dtls_cb_t handler, void *handler_arg);
|
||||
|
||||
/**
|
||||
* @brief Close a possibly async DTLS socket
|
||||
*
|
||||
* Helper function that closes a possibly async socket on the event thread.
|
||||
*
|
||||
* @param sock socket
|
||||
*/
|
||||
void sock_dtls_event_close(sock_dtls_t *sock);
|
||||
#endif /* defined(MODULE_SOCK_DTLS) || defined(DOXYGEN) */
|
||||
|
||||
#if defined(MODULE_SOCK_IP) || defined(DOXYGEN)
|
||||
@ -208,6 +224,15 @@ void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
|
||||
*/
|
||||
void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
|
||||
sock_ip_cb_t handler, void *handler_arg);
|
||||
|
||||
/**
|
||||
* @brief Close a possibly async IP socket
|
||||
*
|
||||
* Helper function that closes a possibly async socket on the event thread.
|
||||
*
|
||||
* @param sock socket
|
||||
*/
|
||||
void sock_ip_event_close(sock_ip_t *sock);
|
||||
#endif /* defined(MODULE_SOCK_IP) || defined(DOXYGEN) */
|
||||
|
||||
#if defined(MODULE_SOCK_TCP) || defined(DOXYGEN)
|
||||
@ -226,6 +251,15 @@ void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
|
||||
void sock_tcp_event_init(sock_tcp_t *sock, event_queue_t *ev_queue,
|
||||
sock_tcp_cb_t handler, void *handler_arg);
|
||||
|
||||
/**
|
||||
* @brief Close a possibly async TCP socket
|
||||
*
|
||||
* Helper function that closes a possibly async socket on the event thread.
|
||||
*
|
||||
* @param sock socket
|
||||
*/
|
||||
void sock_tcp_event_close(sock_tcp_t *sock);
|
||||
|
||||
/**
|
||||
* @brief Makes a TCP listening queue able to handle asynchronous events using
|
||||
* @ref sys_event.
|
||||
@ -257,8 +291,28 @@ void sock_tcp_queue_event_init(sock_tcp_queue_t *queue, event_queue_t *ev_queue,
|
||||
*/
|
||||
void sock_udp_event_init(sock_udp_t *sock, event_queue_t *ev_queue,
|
||||
sock_udp_cb_t handler, void *handler_arg);
|
||||
|
||||
/**
|
||||
* @brief Close a possibly async UDP socket
|
||||
*
|
||||
* Helper function that closes a possibly async socket on the event thread.
|
||||
*
|
||||
* @param sock socket
|
||||
*/
|
||||
void sock_udp_event_close(sock_udp_t *sock);
|
||||
|
||||
#endif /* defined(MODULE_SOCK_UDP) || defined(DOXYGEN) */
|
||||
|
||||
/**
|
||||
* @brief clear any pending socket async events
|
||||
*
|
||||
* @warning Do not call this in the application, it is automatically called by
|
||||
* sock_*_close().
|
||||
*
|
||||
* @param[in] async_ctx socket async context
|
||||
*/
|
||||
void sock_event_close(sock_async_ctx_t *async_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
|
||||
#include "gnrc_sock_internal.h"
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
#include "net/sock/async/event.h"
|
||||
#endif
|
||||
|
||||
int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local,
|
||||
const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags)
|
||||
{
|
||||
@ -65,6 +69,9 @@ void sock_ip_close(sock_ip_t *sock)
|
||||
{
|
||||
assert(sock != NULL);
|
||||
gnrc_netreg_unregister(GNRC_NETTYPE_IPV6, &sock->reg.entry);
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_ip_get_async_ctx(sock));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *local)
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
#include "net/udp.h"
|
||||
#include "random.h"
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
#include "net/sock/async/event.h"
|
||||
#endif
|
||||
|
||||
#include "gnrc_sock_internal.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
@ -155,6 +159,9 @@ void sock_udp_close(sock_udp_t *sock)
|
||||
{
|
||||
assert(sock != NULL);
|
||||
gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &sock->reg.entry);
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_event_close(sock_udp_get_async_ctx(sock));
|
||||
#endif
|
||||
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||
if (_udp_socks != NULL) {
|
||||
gnrc_sock_reg_t *head = (gnrc_sock_reg_t *)_udp_socks;
|
||||
|
||||
@ -62,6 +62,100 @@ static void _set_ctx(sock_async_ctx_t *ctx, event_queue_t *ev_queue)
|
||||
ctx->queue = ev_queue;
|
||||
}
|
||||
|
||||
void sock_event_close(sock_async_ctx_t *async_ctx)
|
||||
{
|
||||
event_queue_t *queue = async_ctx->queue;
|
||||
if (!queue) {
|
||||
/* no callback registered */
|
||||
return;
|
||||
}
|
||||
|
||||
/* RIOTs socket API is not thread safe so we assume that wherever this is
|
||||
* called from it's not racing against some other socket usage.
|
||||
*
|
||||
* But we have to go stricter and assume this is called from the same thread
|
||||
* that processes the events. There is no way of preventing the networking
|
||||
* subsystem from posting socket events until the socket has been
|
||||
* unregistered, which is only happening when closing the socket and the
|
||||
* reason we're here in the first place. */
|
||||
assume(!queue->waiter || thread_getpid_of(queue->waiter) == thread_getpid());
|
||||
|
||||
event_cancel(async_ctx->queue, &async_ctx->event.super);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
#if defined(MODULE_SOCK_UDP) || defined(DOXYGEN)
|
||||
SOCK_ASYNC_UDP,
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_TCP) || defined(DOXYGEN)
|
||||
SOCK_ASYNC_TCP,
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_IP) || defined(DOXYGEN)
|
||||
SOCK_ASYNC_IP,
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_DTLS) || defined(DOXYGEN)
|
||||
SOCK_ASYNC_DTLS,
|
||||
#endif
|
||||
} sock_async_t;
|
||||
|
||||
typedef struct {
|
||||
event_t super;
|
||||
sock_async_t type;
|
||||
void *sock;
|
||||
} _sock_close_ev;
|
||||
|
||||
static void _sock_event_close_cb(event_t *ev)
|
||||
{
|
||||
_sock_close_ev *close_ev = container_of(ev, _sock_close_ev, super);
|
||||
|
||||
switch (close_ev->type) {
|
||||
#if defined(MODULE_SOCK_UDP) || defined(DOXYGEN)
|
||||
case SOCK_ASYNC_UDP:
|
||||
sock_udp_close(close_ev->sock);
|
||||
break;
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_TCP) || defined(DOXYGEN)
|
||||
case SOCK_ASYNC_TCP:
|
||||
sock_tcp_disconnect(close_ev->sock);
|
||||
break;
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_IP) || defined(DOXYGEN)
|
||||
case SOCK_ASYNC_IP:
|
||||
sock_ip_close(close_ev->sock);
|
||||
break;
|
||||
#endif
|
||||
#if defined(MODULE_SOCK_DTLS) || defined(DOXYGEN)
|
||||
case SOCK_ASYNC_DTLS:
|
||||
sock_dtls_close(close_ev->sock);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void _sock_event_close_common(void *sock, sock_async_ctx_t *async_ctx,
|
||||
sock_async_t type)
|
||||
{
|
||||
_sock_close_ev ev = {
|
||||
.super.handler = _sock_event_close_cb,
|
||||
.type = type,
|
||||
.sock = sock,
|
||||
};
|
||||
|
||||
if (!async_ctx->queue ||
|
||||
!async_ctx->queue->waiter ||
|
||||
thread_getpid_of(async_ctx->queue->waiter) == thread_getpid()) {
|
||||
/* - this socket is not async OR
|
||||
* - there is no thread processing the event queue (in which case we
|
||||
* might race against @ref event_queue_claim() but so is life)
|
||||
* OR we are on the event queue thread. In the first case we might
|
||||
* block forever, in the second we surely will, so do it now. */
|
||||
_sock_event_close_cb(&ev.super);
|
||||
return;
|
||||
}
|
||||
|
||||
event_post(async_ctx->queue, &ev.super);
|
||||
event_sync(async_ctx->queue);
|
||||
}
|
||||
#ifdef MODULE_SOCK_DTLS
|
||||
static void _dtls_cb(sock_dtls_t *sock, sock_async_flags_t type, void *arg)
|
||||
{
|
||||
@ -77,6 +171,11 @@ void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
|
||||
ctx->event.cb.dtls = handler;
|
||||
sock_dtls_set_cb(sock, _dtls_cb, handler_arg);
|
||||
}
|
||||
|
||||
void sock_dtls_event_close(sock_dtls_t *sock)
|
||||
{
|
||||
_sock_event_close_common(sock, sock_dtls_get_async_ctx(sock), SOCK_ASYNC_DTLS);
|
||||
}
|
||||
#endif /* MODULE_SOCK_DTLS */
|
||||
|
||||
#ifdef MODULE_SOCK_IP
|
||||
@ -94,6 +193,11 @@ void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
|
||||
ctx->event.cb.ip = handler;
|
||||
sock_ip_set_cb(sock, _ip_cb, handler_arg);
|
||||
}
|
||||
|
||||
void sock_ip_event_close(sock_ip_t *sock)
|
||||
{
|
||||
_sock_event_close_common(sock, sock_ip_get_async_ctx(sock), SOCK_ASYNC_IP);
|
||||
}
|
||||
#endif /* MODULE_SOCK_IP */
|
||||
|
||||
#ifdef MODULE_SOCK_TCP
|
||||
@ -127,6 +231,11 @@ void sock_tcp_queue_event_init(sock_tcp_queue_t *queue, event_queue_t *ev_queue,
|
||||
ctx->event.cb.tcp_queue = handler;
|
||||
sock_tcp_queue_set_cb(queue, _tcp_queue_cb, handler_arg);
|
||||
}
|
||||
|
||||
void sock_tcp_event_close(sock_tcp_t *sock)
|
||||
{
|
||||
_sock_event_close_common(sock, sock_tcp_get_async_ctx(sock), SOCK_ASYNC_TCP);
|
||||
}
|
||||
#endif /* MODULE_SOCK_TCP */
|
||||
|
||||
#ifdef MODULE_SOCK_UDP
|
||||
@ -144,6 +253,12 @@ void sock_udp_event_init(sock_udp_t *sock, event_queue_t *ev_queue,
|
||||
ctx->event.cb.udp = handler;
|
||||
sock_udp_set_cb(sock, _udp_cb, handler_arg);
|
||||
}
|
||||
|
||||
void sock_udp_event_close(sock_udp_t *sock)
|
||||
{
|
||||
_sock_event_close_common(sock, sock_udp_get_async_ctx(sock), SOCK_ASYNC_UDP);
|
||||
}
|
||||
|
||||
#endif /* MODULE_SOCK_UDP */
|
||||
|
||||
/** @} */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user