Repository navigation
Fix/stability - #5
Merged
Merged
Conversation
Engine: - A uTP dial that never connected leaked its rx/tx/bitfield (~516 KB each): sess_close now frees the session in the connecting branch too. - The DHT thread no longer calls dht_search under s_bg_mtx: jech answers from local storage synchronously through bg_on_event, which takes the same (non-recursive) lock -- a node announcing our hash wedged the thread, and the netloop and torrentfs_close behind it. - dht_find_peers waits for in-flight callbacks before its caller frees ctx. - Blocks from incoming peers are tagged -1 (was peer_gen[-1], which blamed and could ban pool slot 2047). - The SD cache reads only DONE pieces (a slot exists before its write ends). - select_file during shutdown no longer frees aq buffers under the netloop. - meta_pipe_run closes only threads it created. - sess_close reads the MSE flags before peer_nb_free zeroes them (the plaintext-retry branch was dead); rotate_out counts choked peers again. - Each live engine gets its own cache file name (slot): the next episode's engine opens before the previous one closes, and both used cache.bin. App: - Updates download to .part and are checked (NRO0 magic, header size, release size, fclose) before becoming .new; a broken .new is dropped. - Home's Continue row parks the focus on the screen itself when neither the hero nor a poster row exists, and only rebuilds while on top. - Stremio catalogs landing under a detail screen wait until the tab is on top (ui::isOnTop) instead of freeing the card on the focus stack. - The library +/- answer touches its view only while it is still focused. - g_libIds is published on the UI thread. - borealis: exceptions in brls::async tasks are caught (VENDORED.md #9). Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Magnet metadata: each peer's fetch now ends on the pipeline's stop flag (deadline, cancel, another worker's success) and after 30 s; a peer trickling keep-alives held a worker, and the open, forever. Test 8 in test_suite covers it (it hangs without the fix). - The player's engine open runs on the worker pool and is cancellable: Back stops a magnet's fetch. A small hand-off makes exactly one of the task, its callback and the destructor close an engine opened after Back (also on app exit, where no brls::sync runs). TorrServer resolves and the update download moved off brls::async too; so did the Local tab's magnet name resolves, which torrent_meta_abort_all ends on exit. - App exit: exitEvent aborts the network and magnet fetches before borealis joins its task thread; exitDoneEvent writes the library (library::flush), whose last save was queued and dropped. - The end of a file (or next/previous episode) with the settings panel open pops the panel too (popPlayerThen finds the player in the stack): it closed only the panel, or pushed a second player over the first. - The "video playing" flag is counted per live player: the next episode's player is built before the previous one's destructor turned it off. - A torrent:// stream has a cancel_fn of its own (torrentfs_read_cancel); an nxhttps:// open can be abandoned (httpsrc_open_abortable) so the destructor does not wait it out on the UI thread; stream_http_err resets per open. - SD cache: a DONE piece that cannot be read back is fetched again instead of freezing the picture. - The listener's socket is closed by its own thread only. - A block for the blocked reader wakes it under the lock (no lost wakeup). - A failed open keeps its reason on screen and leaves on one Back. Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- fsutil.hpp (header-only): writeAtomic writes through .tmp with every write checked and keeps the previous version as .bak; readFirst falls back to the .tmp of a save cut between its renames, then to the .bak, when a file is missing or cut short (looksComplete). Used by config.json, library.json, history.json, the Stremio key and e-mail, the voice choices and magnet.txt -- several were rewritten in place, and a power cut left them empty. test_library checks the fallbacks. - config.json values are JSON-escaped (a quote in a value broke the file); the reader understands what is escaped and reads old files unchanged. - http: 15 s connect timeout and NOSIGNAL on every request (curl's default connect timeout is 300 s), answers held in memory capped at 32 MB. - A .torrent is downloaded to .part and renamed when whole, so a failed refetch no longer deletes the file history/Continue resume from; a Jackett release played before uses its cached .torrent (works with Jackett down). - TMDB and the Stremio addons treat non-2xx answers as failures: a proxy's 502 page was cached over the good copy for hours, an addon's 500 cached as "no episodes". Genres from a failed manifest are no longer cached. - TMDB's cache write is checked and leaves no .tmp behind. - Subtitles download to .part, and two requests for one file share it. - UDP tracker transaction ids come from a local generator: srand(time) on every announce made them predictable and reset the DHT's rand(). - A reused peer pool slot clears its uTP-retry and plaintext-only flags. Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Player: - A direct stream that dies mid-file (it reaches mpv as the end of the file) reconnects where it stopped, up to three times, instead of closing the player and marking the title watched; after that it says so and B leaves. Checked on the PC by killing and restarting the test server mid-play. - A file of the pack that is not a nameable episode plays as a plain file: it kept the previous episode's identity and wrote its progress there. - The episode list no longer shows the playing episode's progress on unplayed files. - A seek (back to 0:00 too) is the position saved on leaving. - OK three times unlocks only in a row. Engine: - DHT targets are keyed by (hash, owner): the next episode's engine and the previous one share a hash for a moment, and the old one's removal took the new one's DHT discovery with it. Peers go to every owner of a hash; each hash is searched once. - MSE: the VC resync expects the first 8 keystream bytes at any padB offset (it only worked for padB == 0). MSE stays off; the note asks for a new A/B. - UPnP maps the port with a one-hour lease renewed while running (permanent only where the router insists) and deletes the mapping on the way out. Parsing: - "S01E05 - 720p" and "S02 - 480p" are no longer episode/season ranges up to 720/480 (a letter after the number, an end below the start, or past 99/999 is not a range end). test_release covers it. - json: escape() escapes control characters, a lone surrogate or \u0000 reads as U+FFFD, integer() saturates. test_tmdb covers it. Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Peer receive buffers start at 64 KB and double up to 512 KB only for a peer that fills them: every session took 512 KB, ~20 MB at 40 sessions. - Card artwork is decoded on a worker and only uploaded on the UI thread (ui::loadImageAsync); a screen of cards decoded dozens of JPEGs, a w1280 backdrop is 3.6 MB of pixels, in one frame. - borealis keeps at most 48 textures no view uses (was 200 -- hundreds of MB of backdrops after a browse); textures in use are never dropped. - The Continue row has its own liveness token: artwork landing for a card freed by a rebuild no longer reaches it. - http::get/postJson reuse one curl handle per thread, keeping connections and TLS sessions: the posters of a screen share a connection instead of a handshake each. http::shutdown() closes them before main() returns. - borealis' task thread waits for work instead of sleeping 500 ms between batches (VENDORED.md #9): every brls::async task started up to half a second late. - tmdb::clearCache walks the SD card on a worker; "Test connection" asks once the clearing is done. - mpv's verbose log is requested only with the log file on. - The magnet file-list cache is read once per change, not once per row. Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- WebP posters are checked before decoding: a file declaring 16k x 16k pixels was a 1 GB allocation (posters are at most 4096 a side). - HTTP tracker replies are capped at 512 KB (was 4 MB): an announce reply is a few KB, and the cap bounds the bencode tree an unverified tracker can make us build. - The preferred subtitle language is read on the UI thread, not on the worker sorting the results. - CLAUDE.md: the rules this work turned up (two players alive at once, popPlayerThen, screens under another activity, long work off brls::async, fsutil saves, HTTP status before caching, kept curl handles). Not compiled for the Switch yet (PC build and pctest only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
No description provided.