Commit Graph

509 Commits

Author SHA1 Message Date
Max Kellermann cd4b673b6c event/WakeFD: convert macro to class with a GetSocket() method 2021-01-11 17:02:54 +01:00
Max Kellermann abbd980671 Merge branch 'v0.22.x' 2021-01-01 19:59:15 +01:00
Max Kellermann 5348f8c9c8 copyright year 2021 2021-01-01 19:54:28 +01:00
arcnmx 0a81e462db event/SocketEvent: remove FD before closing socket
SocketEvent knows the FD is still open and is about to close it, so
it's unnecessary to rely on the kernel (via AbandonFD) to clean up the
epoll_wait list.

### Why this is relevant

- `AbandonFD` assumes that upon closing the socket, the FD will be automatically removed from the epoll list. That fd is associated with a reference to the `SocketEvent`, so this is an important and dangerous assumption to get wrong. In the case that the FD isn't immediately removed from the list by the kernel, the event loop can crash due to the `SocketEvent` being destroyed and it being a use-after-free bug at that point.
- If a socket FD happens to be duplicated, then closing the SocketEvent FD will not automatically remove it from epoll, and will trigger said bug/crash. It is only automatically removed when all FD references to the underlying socket/resource are closed?
- A `fork()` is one example where a socket FD can be duplicated and result in this situation.
    - `CLOEXEC` might be considered mitigation for this but also introduces a race condition where the crash can occur between a `fork()` and `exec()` without additional synchronization to freeze the event loop.

One could argue the mpd event loop isn't fork-safe, and thus should be allowed to use `AbandonFD` however it likes. A decision on whether this is intended should probably be declared; but either way this fix seems appropriate in cases where `Abandon` isn't actually necessary. It also might be possible to fix `AbandonFD` to mark the `SocketEvent` as removed without using `EPOLL_CTL_DEL`?

[edit: made this dependent on HAVE_THREADED_EVENT_LOOP which is always
true for MPD, but not for ncmpc, for example - mk]
2020-12-04 10:32:46 +01:00
Max Kellermann 5cbbe8ae2e event/TimerEvent: update API documentation 2020-12-04 09:57:19 +01:00
Max Kellermann 00fafa16c7 event/SocketEvent: remove assert(), reduce header dependencies 2020-12-04 09:56:28 +01:00
Max Kellermann cea8db7eaa event/SocketEvent: add comment 2020-12-04 09:55:08 +01:00
Max Kellermann b56c0e69e4 event/SocketEvent: add another assert() to Open() 2020-12-04 09:24:02 +01:00
Max Kellermann b27e82e4a9 event/SocketEvent: allow Schedule() with IMPLICIT_FLAGS
Relax the API (instead of tightening it further like commit
7bc1c9925b tried to do unsuccessfully).
2020-12-04 09:17:45 +01:00
Max Kellermann ad48834469 Revert "event/SocketEvent: add assert()"
This reverts commit 7bc1c9925b.  It
caused a crash with the ALSA plugin family (through
MultiSocketMonitor::ReplaceSocketList() and
MultiSocketMonitor::AddSocket()).  Until we have a proper fix, the
assertion patch is reverted.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1020
2020-12-02 20:43:29 +01:00
Max Kellermann 9d6b5e2ba1 event/TimerEvent: rename IsActive() to IsPending() 2020-12-02 15:41:11 +01:00
Max Kellermann 33ba190bec event/TimerEvent: add ScheduleEarlier() 2020-12-02 15:30:37 +01:00
Max Kellermann 3783350d25 event/SocketEvent: document Dispatch() 2020-12-02 15:24:23 +01:00
Max Kellermann 173405a343 event/SocketEvent: make Dispatch() private 2020-12-02 15:14:51 +01:00
Max Kellermann 7bc1c9925b event/SocketEvent: add assert() 2020-12-02 15:12:30 +01:00
Max Kellermann 4e88f95f94 event/Loop: move the "again" check out of the mutex scope 2020-12-01 20:29:21 +01:00
Max Kellermann 790e540c19 event/Loop: use ClockCache 2020-12-01 20:25:42 +01:00
Max Kellermann 2a1dd55b11 event/Loop: include cleanup 2020-12-01 20:19:40 +01:00
Max Kellermann be20f760ab event/Loop: disallow copying 2020-12-01 20:18:33 +01:00
Max Kellermann 8050394003 event/Loop: add noexcept 2020-12-01 20:10:53 +01:00
Max Kellermann ff8b5bc61b event/Loop: reorder methods 2020-12-01 20:09:25 +01:00
Max Kellermann ef8797821f event/Loop: inline field initializers 2020-12-01 20:07:35 +01:00
Max Kellermann 5f2797e7cc event/Loop: add more assertions to dtor 2020-12-01 20:05:54 +01:00
Max Kellermann e286702f4c event/Loop: rename AddDeferred() to AddDefer() 2020-12-01 17:26:39 +01:00
Max Kellermann c58aaf545f event/IdleEvent: make a special case of DeferEvent 2020-12-01 17:14:24 +01:00
Max Kellermann 990f2dc1cf event/DeferEvent: use class IntrusiveList instead of boost::intrusive::list 2020-12-01 17:14:24 +01:00
Max Kellermann 774b4313f2 event/DeferEvent: split the thread-safe version into new class InjectEvent 2020-12-01 17:14:24 +01:00
Max Kellermann 1ecbc2ff0f event/DeferEvent: explicitly forbid copying 2020-12-01 17:14:24 +01:00
Max Kellermann fd8e38f8cd event/DeferEvent: use using instead of typedef 2020-12-01 17:14:24 +01:00
Max Kellermann 3d276d50b4 event/PollBackend: use vector::push_back() instead of resize() 2020-10-30 16:35:20 +01:00
Max Kellermann b1b731340e event/PollBackend: add Item constructor 2020-10-30 16:32:45 +01:00
Max Kellermann b9b02b4ff2 event/PollBackend: use unordered_map::find() instead of operator[]
The latter creates a new object, but we know that the key already
exists.
2020-10-30 16:25:41 +01:00
Max Kellermann ab5d23da11 event/PollBackend: use unordered_map::emplace() in Add() 2020-10-30 16:24:32 +01:00
Max Kellermann 0554fe3652 event/PollBackend: use std::size_t 2020-10-30 16:09:29 +01:00
Max Kellermann b0282fe36f event/PollGroupWinSelect: add Item constructor 2020-10-30 16:07:23 +01:00
Max Kellermann 69b45e693b event/WinSelect: use unordered_map::find() instead of operator[]
The latter creates a new object, but we know that the key already
exists.
2020-10-30 16:05:25 +01:00
Max Kellermann 9e97acc28d event/WinSelect: merge duplicate code into ApplyReady() 2020-10-30 15:55:23 +01:00
Max Kellermann b1e446a931 event/WinSelect: add missing const to deleted copy ctor/operator 2020-10-30 15:45:29 +01:00
Max Kellermann 938319cd44 event/WinSelect: reorder method prototypes 2020-10-30 15:45:12 +01:00
Max Kellermann fee29001fa event/WinSelect: use unordered_map::emplace() in Add()
This allow using erase() with iterator, without a key lookup.
2020-10-30 15:32:11 +01:00
Max Kellermann 6d894a1806 event/WinSelect: use SOCKET as std::unordered_map key 2020-10-30 15:25:09 +01:00
Rosen Penev 0fd2c74a66 use structured binding declarations
Shorter.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-28 15:41:31 -07:00
Max Kellermann 7c47fe746c event/Loop: AbandonFD() unlinks the SocketEvent
Fixes use-after-free bugs causing assertion failures at shutdown,
because all "abandoned" SocketEvents are still in the linked list.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/986
Closes https://github.com/MusicPlayerDaemon/MPD/issues/987
2020-10-28 15:01:32 +01:00
Max Kellermann 65a1c4a016 event/Loop: pass SocketEvent& to AbandonFD() 2020-10-28 14:59:28 +01:00
Max Kellermann 46418d0f2d event/ServerSocket: remove obsolete API documentation 2020-10-28 14:52:31 +01:00
Max Kellermann 8348a1ec8f event/PollGroup: rename to PollBackend 2020-10-19 14:52:59 +02:00
Max Kellermann c18e00daa4 event/PollGroup: move event flags to a separate header
Reduce header dependencies for SocketEvent.hxx.
2020-10-19 14:48:41 +02:00
Max Kellermann 418ba96334 event/SocketEvent: forbid copying 2020-10-18 20:07:49 +02:00
Max Kellermann a60e782959 event/Loop: reorder assertions 2020-10-18 20:05:22 +02:00
Max Kellermann 8bab5733d7 event/Loop: add assertions 2020-10-18 20:04:16 +02:00