asio: set FD_CLOEXEC on listen + UDP sockets - #552
Merged
mrjimenez merged 1 commit intoMay 11, 2026
Conversation
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
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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), whichfork()s andexec()s. WithoutFD_CLOEXECon 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 withAddress already in use.Fix
FD_CLOEXECon the acceptor immediately afteropen()inCAsioSocketServerImpl::CAsioSocketServerImpl().CAsioUDPSocketImpl::CreateSocket()to open + bind in two steps (instead of the bind-on-construct overload) so the same treatment fits cleanly between them.SetCloexecOnSocket(); on Windows it's a no-op because WinSockSOCKEThandles are non-inheritable unless the parent passesbInheritHandle=TRUEtoCreateProcess(whichwxExecutedoes not).Reproduction + verification
Standalone repro on Ubuntu 26.04 ARM64 (boost::asio 1.83): bind to port 54321, fork+exec
sleep 10, parent exits, observess -tlnp: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 throughwxExecute, 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