Skip to content

asio: set FD_CLOEXEC on listen + UDP sockets - #552

Merged
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/asio-cloexec-on-bound-sockets
May 11, 2026
Merged

asio: set FD_CLOEXEC on listen + UDP sockets#552
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/asio-cloexec-on-bound-sockets

Conversation

@got3nks

@got3nks got3nks commented May 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #172 ("vlc listening on amule's port when closed"). The root cause is exactly what nachtgeist suspected — wx ran the video preview via wxExecute(vlc), which fork()s and exec()s. Without FD_CLOEXEC on the bound sockets, the child inherits aMule's TCP listen FD and UDP FD; when aMule exits, vlc still holds those FDs, the kernel keeps the binds active, and the next aMule start fails with Address already in use.

Fix

  • Set FD_CLOEXEC on the acceptor immediately after open() in CAsioSocketServerImpl::CAsioSocketServerImpl().
  • Refactor CAsioUDPSocketImpl::CreateSocket() to open + bind in two steps (instead of the bind-on-construct overload) so the same treatment fits cleanly between them.
  • Wrap the fcntl call in SetCloexecOnSocket(); on Windows it's a no-op because WinSock SOCKET handles are non-inheritable unless the parent passes bInheritHandle=TRUE to CreateProcess (which wxExecute does not).

Reproduction + verification

Standalone repro on Ubuntu 26.04 ARM64 (boost::asio 1.83): bind to port 54321, fork+exec sleep 10, parent exits, observe ss -tlnp:

without fix: LISTEN ... 0.0.0.0:54321 ... users:(("sleep",pid=187175,fd=3))   # leaked
with fix:    (no listener)                                                    # freed

Same path the bug takes through aMule + vlc.

Known gap

Outgoing TCP client sockets (connect() / async_connect()) and accepted peer connections (async_accept() completion) also inherit through wxExecute, but they bind to ephemeral source ports so they don't block subsequent aMule starts — they're a minor FD leak in the spawned child but don't manifest as the user-visible #172 regression. Closing those gaps would require structural changes around the existing async-flow completion handlers; left for a follow-up.

Closes #172

Without close-on-exec, every fd aMule has open at the moment of a
fork+exec (preview-with-vlc, configured external-command hooks,
amuleweb child, etc.) gets inherited by the spawned child. The
TCP listen socket and the eD2k UDP socket are the long-lived ones:
when the user previews a file and leaves vlc open after closing
aMule, vlc still holds the bind, and the next aMule start fails
with 'Address already in use' until vlc is killed.

Set FD_CLOEXEC on the acceptor immediately after open(), and refactor
the UDP CreateSocket() to open + bind in two steps so the same
treatment fits in between. The fcntl call is wrapped in
SetCloexecOnSocket(); on Windows it's a no-op because WinSock SOCKET
handles are non-inheritable unless the parent passes
bInheritHandle=TRUE to CreateProcess (which wxExecute does not).

Reproduced + verified on Ubuntu 26.04 ARM64:

  fork+exec sleep, parent exits, ss output --
    no fix: 'LISTEN ... users:(("sleep", fd=3))'  port held
    fix:    no listener                              port freed

Outgoing TCP client sockets and accepted peer connections also
inherit through wxExecute, but they use ephemeral source ports so
they don't block subsequent aMule starts -- left as a known minor
gap that would require restructuring around connect()/async_accept()
completion handlers. The user-visible amule-project#172 regression is fully
addressed by the listen + UDP fix.

Closes amule-project#172
@mrjimenez
mrjimenez merged commit 613a9ce into amule-project:master May 11, 2026
12 checks passed
@got3nks
got3nks deleted the fix/asio-cloexec-on-bound-sockets branch May 11, 2026 08:01
got3nks added a commit to got3nks/amule that referenced this pull request Jul 23, 2026
it_CH was not a Swiss-Italian localization but a stale, degraded copy of
it: 1531 of 1845 strings (83%) were byte-identical to it, and the
divergences were older translator-choice variants (cartella/directory,
collegamento/link, fallito/non riuscito) rather than Helvetisms, plus
~68 unreviewed fuzzy matches and ~140 strings left untranslated that it
already covers.

gettext only falls back it_CH -> it -> C when it_CH.mo is absent, so
shipping this catalog gave Swiss-Italian users a worse result than plain
Italian (English strings where it is complete). Removing it lets those
users fall through to the full, current it catalog.

Also drops the now-dead it_CH wiring: the LINGUAS entry, the po/
CMakeLists.txt language label, the redundant [it_CH] .desktop keys
(identical to [it]), and the it_CH -> ITALIAN mapping in the Windows
NSIS generator. it_CH was app-catalog only (no man pages).
got3nks added a commit to got3nks/amule that referenced this pull request Jul 23, 2026
)

The it_CH catalog file was removed in amule-project#552, but the surrounding
references were left behind: the LINGUAS entry, the po/CMakeLists.txt
language label, the redundant [it_CH] .desktop keys (identical to
[it]), and the it_CH -> ITALIAN mapping in the Windows NSIS generator.

None affect the build (it is glob-driven and it_CH.po is already gone),
but they point at a catalog that no longer exists. Remove them so the
tree is consistent.
got3nks added a commit to got3nks/amule that referenced this pull request Jul 23, 2026
)

The it_CH catalog was dropped in amule-project#552, but the language picker is not
driven by the shipped catalogs: it iterates the hardcoded
aMuleLanguages[] table in Preferences.cpp, which still listed
wxLANGUAGE_ITALIAN_SWISS. Removing the catalog could not hide it,
because UpdateChoice()'s probe marks an entry available when wxLocale
reports PACKAGE loaded, and wxLocale falls back it_CH -> it -- so it.mo
kept satisfying the check and the entry stayed visible.

Remove the table entry (the picker-side twin of the catalog drop) and
drop the now-unused 'Italian (Swiss)' string from the po catalogs.
Catalogs edited surgically to keep the diff to the removed entry; the
stale source-line references CI already tolerates are left untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vlc listening on amule's port when closed

2 participants