2019-10-27 11:46:18 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
|
|
struct fdm;
|
|
|
|
|
|
|
|
|
|
typedef bool (*fdm_handler_t)(struct fdm *fdm, int fd, int events, void *data);
|
|
|
|
|
|
|
|
|
|
struct fdm *fdm_init(void);
|
|
|
|
|
void fdm_destroy(struct fdm *fdm);
|
|
|
|
|
|
|
|
|
|
bool fdm_add(struct fdm *fdm, int fd, int events, fdm_handler_t handler, void *data);
|
|
|
|
|
bool fdm_del(struct fdm *fdm, int fd);
|
fdm: don't free FD data that may be referenced by epoll return data
It is perfectly possible, and legal, for a FDM handler to delete
another handler. The problem however is when the epoll returned array
of FD events contain the removed FD handler *after* the handler that
removed it.
That is, if the epoll returned array is:
[FD=13, FD=37]
and the handler for FD=13 removes FD=37, then given the current
implementation, the FD user data (our handler callback etc) will point
to a free:d address.
Add support for this situation by deferring FD handler removal *when
called from another handler*.
This is done by "locking" the FDM struct before looping the handlers
for FDs with events (and unlocking afterwards).
In fdm_del(), we check if the FDM has been locked, in which case the
FD is marked as deleted, and put on a deferred list. But
not *actually* deleted.
Meanwhile, in the FDM poll function, we skip calling handlers for
marked-for-deletion FDs.
Then, when all FDs have been processed, we loop the deferred list and
finally deletes the FDs for real.
2019-11-01 19:51:33 +01:00
|
|
|
bool fdm_del_no_close(struct fdm *fdm, int fd);
|
2019-10-27 11:46:18 +01:00
|
|
|
|
2019-11-03 00:22:22 +01:00
|
|
|
bool fdm_event_add(struct fdm *fdm, int fd, int events);
|
|
|
|
|
bool fdm_event_del(struct fdm *fdm, int fd, int events);
|
|
|
|
|
|
2019-10-27 11:46:18 +01:00
|
|
|
bool fdm_poll(struct fdm *fdm);
|