fix(amuled): construct partFile write/hash threads after InitGui fork (#849) - #850
Merged
mrjimenez merged 1 commit intoJun 4, 2026
Conversation
amuled's --full-daemon (-f) mode forks from inside InitGui() at amule.cpp:672. On POSIX, fork() only carries the calling thread to the child — any thread spawned before the fork has its OS-level pthread torn off, leaving the C++ object in memory with no thread actually running behind it. CPartFileWriteThread and CPartFileHashThread (both wxThread-backed, both spawned in their ctor) were constructed at amule.cpp:652-653, which is BEFORE the InitGui() fork. The comment at amule.cpp:682 explicitly flags this constraint for the same-shaped UploadBandwidthThrottler / CUploadDiskIOThread / CAsioService trio right next door — but the partfile-* threads, added later (amule-project#454), skipped it. User-visible symptom (amule-project#849): amuled -f reaches 99% on the network side, but the .part file stays at 0 bytes and CPU is pegged. The write-thread's PB_PENDING queue keeps filling because nothing is draining it on the child. Monolithic amule and amuled without -f both work because neither forks. The synchronous FlushBuffer fallback at PartFile.cpp:3252 doesn't save us either, because wxThread::IsRunning() reads an internal state flag that still says "running" post-fork — items get marked PB_PENDING and routed at the dead thread instead of being written inline. Fix: move the two constructions past InitGui(), into the same post-fork group as uploadDiskIOThread. No other code between the old and new construction sites touches either pointer (verified by grep in src/amule.cpp).
got3nks
added a commit
to got3nks/amule
that referenced
this pull request
Jun 7, 2026
…ule-project#912) Extends existing categories (preferring extensions over new lines): - Performance/Upload: amule-project#898 SlotAllocation default raised. - Networking & Discovery: wire-parser hardening list extended with amule-project#879/amule-project#882/amule-project#890/amule-project#886; new amuleweb security hardening bullet consolidating ngosang's amule-project#869-amule-project#874 triage (all landed in amule-project#875); amulegui list extended with amule-project#857; shared-folder watcher extended with amule-project#858. - Packaging: Windows installer i18n line extended with amule-project#899. - Internals & Refactoring: new docs-polish + code-quality bullets covering amule-project#851/amule-project#855/amule-project#862/amule-project#888/amule-project#900/amule-project#866/amule-project#867/amule-project#895 and amule-project#909/amule-project#910/amule-project#912. - Translations: new pre-release final-wave bullet covering amule-project#847/amule-project#856/ amule-project#891/amule-project#908/amule-project#860/amule-project#904/amule-project#859/amule-project#863/amule-project#861/amule-project#880/amule-project#911/amule-project#901/amule-project#902/amule-project#889/amule-project#868/amule-project#853. - Bug Fixes & Stability: amule-project#850/amule-project#854/amule-project#878/amule-project#906. - CI: ccache wiring (amule-project#892, amule-project#903) + CodeQL binutils-dev (amule-project#907). Contributors footer gains mifritscher and nguyenhoangminhhieu2004-gif (both first-time contributors). PR index extended through amule-project#912.
mrjimenez
pushed a commit
that referenced
this pull request
Jun 8, 2026
Extends existing categories (preferring extensions over new lines): - Performance/Upload: #898 SlotAllocation default raised. - Networking & Discovery: wire-parser hardening list extended with #879/#882/#890/#886; new amuleweb security hardening bullet consolidating ngosang's #869-#874 triage (all landed in #875); amulegui list extended with #857; shared-folder watcher extended with #858. - Packaging: Windows installer i18n line extended with #899. - Internals & Refactoring: new docs-polish + code-quality bullets covering #851/#855/#862/#888/#900/#866/#867/#895 and #909/#910/#912. - Translations: new pre-release final-wave bullet covering #847/#856/ #891/#908/#860/#904/#859/#863/#861/#880/#911/#901/#902/#889/#868/#853. - Bug Fixes & Stability: #850/#854/#878/#906. - CI: ccache wiring (#892, #903) + CodeQL binutils-dev (#907). Contributors footer gains mifritscher and nguyenhoangminhhieu2004-gif (both first-time contributors). PR index extended through #912.
got3nks
added a commit
to got3nks/amule
that referenced
this pull request
Aug 7, 2026
Every ported list appended a 1px trailing spacer on macOS. The reasoning was that macOS hands leftover width to the last *resizable* column and collapses it to nothing once the columns are wider than the control, so a throwaway column should absorb that instead of one the user cares about. CGenericClientListCtrl (amule-project#850) shipped without a spacer and does not collapse, which is what prompted checking the rest. The spacer dates from the first base commit, when every list was still constructed with the legacy wxLC_REPORT|wxSUNKEN_BORDER flags -- and wxLC_REPORT is the same bit as wxDV_VARIABLE_LINE_HEIGHT, so those lists were silently running with variable line height. Those flags came off in 71bdb1a and amule-project#849, and with them gone a spacer-less build shows no collapse. So the spacer appears to have been treating a symptom of the flags rather than a macOS sizing rule. Removing it takes the whole mechanism with it: the six call sites, AppendSpacerColumn(), m_hasSpacer, RealColumnCount()'s adjustment and five COLUMN_*_SPACER ids plus CSearchListModel::COL_SPACER, which each model had to answer for. RealColumnCount() stays as the accessor -- now simply GetColumnCount() -- rather than inlining it across its call sites, which is a separate change.
mrjimenez
pushed a commit
to mrjimenez/amule
that referenced
this pull request
Aug 8, 2026
…ct#850) Last remaining piece of amule-project#801's wxListCtrl -> wxDataViewCtrl migration: the shared base behind CSourceListCtrl and CSharedFilePeersListCtrl. ClientCtrlItem_Struct survives rather than being deleted, unlike the previous ports: one client can be a source or peer of more than one file at a time, so row identity is the (client, owner, type) tuple. Its cached wxBitmap fields are dropped, matching the no-cache precedent from the Shared Files and Downloads ports. Two bar columns, two renderers: CSourceBarRenderer draws the 5-state chunk bar and substitutes a bordered A4AF text badge for those rows, while the peers' availability column needs only the base renderer and ships without SORTABLE, since no comparison exists for it and none did pre-port. The User Name column is a composite icon cluster plus optional country flag plus text, so it goes through CClientNameRenderer, reaching the row via the identity-carrying CBarFillSpec extension point; GetItemColumnText() still answers plain text there, so type-ahead and the accessible row label work off real text rather than the pre-port empty string. CompareItemData() keeps the original SortProc's type precedence, sorting A4AF sources last regardless of direction, before dispatching per column. muuli_wdr.cpp drops the legacy wxLC_REPORT|wxSUNKEN_BORDER flags for both lists.
mrjimenez
pushed a commit
to mrjimenez/amule
that referenced
this pull request
Aug 8, 2026
…endored wxGenericListCtrl (amule-project#855) Follow-up to amule-project#801/amule-project#180: with the client-list port done in amule-project#850, CCommentDialogLst was the only remaining instantiator of CMuleListCtrl and CMuleVirtualListCtrl had no derivers left. CCommentDialogLst drops to a plain wxListCtrl -- a small read-only modal list that does not warrant the CMuleDataViewCtrl treatment -- with click-to-sort reimplemented by hand. amuleDlg's exit-time SaveListControlSettings() widget walk goes too: it existed because CMuleListCtrl only saved lazily from its destructor, which the tray-Exit path could skip, whereas CMuleDataViewCtrl writes column widths and sort orders eagerly on every resize, sort and show/hide, and SaveGUIPrefs() still flushes on every close path. That leaves CMuleVirtualListCtrl, CMuleListCtrl and the vendored wxGenericListCtrl with no consumers, so all four files are deleted. IsListBackgroundDark() moves to MuleColour.h. CListColumnStore's legacy config-migration path is untouched -- it still reads pre-dataview TableWidths* entries. One known simplification: the comments dialog loses its header sort-arrow glyph, which plain wxListCtrl does not draw. A follow-up restores it via ShowSortIndicator().
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.
Closes #849.
Why
amuled -f(full-daemon mode) fails to write any downloaded bytes to the.partfile. Files reach 99 % on the network side (peer state knows it has all the chunks), but~/.aMule/Temp/NNN.partstays at 0 bytes and CPU climbs. Monolithicamuleandamuledwithout-fwork fine.Root cause
CPartFileWriteThreadandCPartFileHashThread(bothwxThread-backed, both spawn the OS thread inside the ctor) are constructed atamule.cpp:652-653, which is beforeInitGui()(line 672) — andInitGui()is where amuled forks. POSIXfork()only carries the calling thread to the child, so in the daemonized child the two thread objects are alive in memory but their OS threads are gone.Three immediately-adjacent thread constructions (
uploadBandwidthThrottler,uploadDiskIOThread,m_AsioService) are correctly placed AFTERInitGui()and have an explicit comment about the fork constraint. The partfile-* pair was added later by the #454 throughput rewrite and missed that constraint.The synchronous-fallback path at
PartFile.cpp:3252-3270doesn't rescue this either:wxThread::IsRunning()reads an internal state flag that still reports "running" after the fork, so items get queued (markedPB_PENDING) onto a dead thread instead of falling through to the inline write branch.Fix
Move lines 652-653 to right after
uploadDiskIOThread, in the same post-fork group. No code between the old and new sites touches either pointer (verified bygrep partFile{WriteThread,HashThread}insrc/amule.cpp).Test plan
amuled -f, and trigger the same ~3 GB download. Expected: the.partfile should start receiving data within seconds and grow as the download progresses, CPU usage should stay normal. No config changes required.amuledwithout-f(no fork): still works (regression-free for that mode).amule: still works (no fork, unaffected).