UPnP: cache failed XML fetches + demote routine discovery logs (#622) - #653
Merged
mrjimenez merged 1 commit intoMay 18, 2026
Merged
Conversation
Two changes that together stop a misbehaving non-WAN device on the
LAN from saturating libupnp's internal thread pool ("ThreadPoolAdd
too many jobs: 100") and turn down the volume of the periodic
service-discovery cycle.
1. Per-URL cache for failed UpnpDownloadXmlDoc() against passive
SSDP ALIVE announcements. A device that re-announces every few
seconds while its HTTP server is unreachable used to pin one
libupnp worker thread per attempt for the full TCP-connect
timeout; with several such devices on the LAN libupnp's pool
saturates and drops jobs.
Add std::map<std::string, time_t> m_failedFetchCache on
CUPnPControlPoint, guarded by a wxMutex. The discovery callback
now consults ShouldSkipAdvertisementFetch() before calling
UpnpDownloadXmlDoc on ALIVE events; if the location URL failed
within FAILED_FETCH_TTL_SECS (300s) the announcement is dropped.
On successful fetch the entry is evicted; on failure its
timestamp is refreshed. SEARCH_RESULT events bypass the cache
since those are active polls initiated from amule's own timer.
Side effect: the inner #if UPNP_VERSION >= 10800 / #else dance
around the UpnpDownloadXmlDoc call and the per-message format
strings collapses since location is now resolved once into a
single const char*. Removes one redundant 'int ret;' from the
legacy < 10800 branch that's no longer needed.
2. Demote two AddDebugLogLineC sites that fire once per service-
discovery cycle on every successful detection -- the
"WAN Service Detected" line in CUPnPService::CUPnPService and
the "Successfully retrieved SCPD Document" line in
CUPnPControlPoint::Subscribe. With amule's periodic re-search
these flood stdout every few minutes on any working IGW;
AddDebugLogLineN keeps them available under Cat_UPnP=1 without
the default-on noise. The actionable error log levels (WAN
service not detected, errors retrieving descriptions) are left
at AddDebugLogLineC.
Reported by @Stoatwblr in amule-project#622 with tcpdump showing the LAN
emitting ~10-13 SSDP advertisements/sec from 5 devices, one of
which is unreachable. The pool error fires in bursts of ~20 at
long intervals -- consistent with the cache refresh cycle for an
unreachable rootdevice.
Closed
mrjimenez
pushed a commit
to mrjimenez/amule
that referenced
this pull request
Jul 28, 2026
…e-project#662) The /eMule/CreateSparseFiles preference was EC-wired and settable from the Web UI but had no control in amule or amuleGUI, so hand-editing amule.conf was the only way to change it. Add a checkbox on the Files preferences page and move the pref from the untracked s_MiscList into the standard NewCfgItem/Cfg_Bool binding used by every sibling control. The setting only does real work when the core runs on Windows -- on POSIX both branches create the part file identically -- so the tooltip documents that, and the monolithic non-Windows build (where inertness is a compile-time certainty) hides the control after creation, keeping the binding intact so the value still round-trips through the config and EC. Closes amule-project#653.
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.
References #622.
Bug
libupnp ThreadPoolAdd too many jobs: 100bursts on busy LANs, even after the NT-based SSDP filter in #623. @Stoatwblr'stcpdumpshows ~10-13 SSDP advertisements/sec from 5 emitters; one of them (a Zyxel mesh WAP at192.168.11.179) announces asupnp:rootdevice(so #623's filter must let it through) but its HTTP server is unreachable, so everyUpnpDownloadXmlDoc()call against it pins a libupnp worker thread for the full TCP-connect timeout. Multiple concurrent fetches from a single misbehaving device saturate libupnp's pool of 100 and trigger the warning in bursts of ~20 at long intervals.Two separate fixes in this PR, both targeting the same issue.
1. Per-URL fetch-failure cache (load reduction)
Add a per-
CUPnPControlPointstd::map<std::string, time_t>keyed on the location URL of failedUpnpDownloadXmlDoc()calls, guarded byCUPnPMutex. The discovery callback now consultsShouldSkipAdvertisementFetch()before callingUpnpDownloadXmlDoc()onUPNP_DISCOVERY_ADVERTISEMENT_ALIVEevents; if the URL has failed withinFAILED_FETCH_TTL_SECS(300 s) the announcement is dropped at the callback entry with no HTTP attempt. On successful fetch the entry is evicted; on failure the timestamp is refreshed.UPNP_DISCOVERY_SEARCH_RESULTevents bypass the cache entirely — those are active polls initiated by amule's own search timer and should attempt the fetch regardless. Only the passive ALIVE bursts (where the device drives the rate) get throttled.The cache stays tiny in practice (handful of misbehaving devices per LAN) and self-prunes via the TTL expiry path on the next post-TTL fetch attempt.
2. Demote two routine log lines (noise reduction)
Two
AddDebugLogLineCsites fire once per service-discovery cycle on every successful WAN-service detection — the "WAN Service Detected" line inCUPnPService::CUPnPService(UPnPBase.cpp:590) and the "Successfully retrieved SCPD Document" line inCUPnPControlPoint::Subscribe(UPnPBase.cpp:1736). Both demoted toAddDebugLogLineN— visible underCat_UPnP=1but no longer default-on stdout noise on every IGW re-search. #627 demoted other UPnP routine logs but missed these two.Actionable errors ("WAN service not detected", "Error retrieving device description") stay at
AddDebugLogLineC.Risk surface
:49152and:49153) are tracked as separate entries — failures on one don't suppress fetches against the other. Matches least-surprise.SEARCH_RESULTpath is untouched, so amule's periodic poll of the network still attempts every URL freshly.#if UPNP_VERSION >= 10800 / #elseblocks that were duplicating identical format strings differing only by which discovery variable they read from; resolved into a singleconst char *locationat the top of the block. The outer#if UPNP_VERSIONshim for actual API differences (struct type, accessor functions) is preserved.Reported by @Stoatwblr in #622 with
tcpdumpadvertising-rate measurements and a full topology breakdown.