Commit 816f7ee3 authored by jan.koester's avatar jan.koester
Browse files

test

parent a1f46ff4
Loading
Loading
Loading
Loading
+54 −6
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <thread>

#include <uuidp.h>

@@ -152,6 +153,14 @@ namespace blogi {
        }

        ~Media(){
            if(_reaperThread.joinable()){
                {
                    std::lock_guard<std::mutex> lk(_reaperMtx);
                    _reaperStop = true;
                }
                _reaperCv.notify_all();
                _reaperThread.join();
            }
        }

        const std::string getName(){
@@ -851,6 +860,10 @@ namespace blogi {

            for (int i = 0; i < Args->maxthreads; ++i)
                _dbAvailableIdx.push_back(i);

            // See _reaperLoop()'s doc comment for why this can't just run
            // opportunistically from _storeStreamState() alone.
            _reaperThread = std::thread([this]{ _reaperLoop(); });
        }

        bool Controller(const int tid,libhttppp::HttpRequest &req,libhtmlpp::HtmlElement *page,const std::string &sessionid){
@@ -1862,12 +1875,23 @@ namespace blogi {
            std::chrono::steady_clock::time_point last_activity = std::chrono::steady_clock::now();
        };

        // Plugins get no callback when the browser-facing connection dies
        // mid-stream (no Disconnect hook in PluginApi), so a StreamState
        // whose owning req is abandoned would otherwise sit in _streams
        // forever — Response() simply stops being called for it, holding
        // its pooled mediadb connection open (and un-drained) permanently.
        // Sweep those out opportunistically whenever a new stream starts.
        // Disconnect(tid, req) exists on PluginApi, but for H2 it is called
        // with the real (persistent, multiplexed) connection object — never
        // with the per-stream `tempreq` that Controller()/Response() actually
        // see and that _streams below is keyed on (HttpEvent::_dispatchH2Stream
        // hands each stream its own throwaway HttpRequest; see httpd.cpp).
        // A browser aborting one image download therefore never matches an
        // entry here, so a StreamState whose owning req is abandoned would
        // otherwise sit in _streams indefinitely — Response() simply stops
        // being called for it, holding its pooled mediadb connection open
        // (and un-drained) permanently.
        //
        // _reaperLoop() below sweeps this on a timer regardless of new
        // traffic — relying solely on the opportunistic call from
        // _storeStreamState() meant a quiet period after a burst of aborted
        // downloads (tab closed, page navigated away mid-load) left those
        // connections held hostage forever, since nothing else would ever
        // call _reapStaleStreamsLocked() again to release them back.
        static constexpr std::chrono::seconds STREAM_IDLE_TIMEOUT{30};

        void _reapStaleStreamsLocked(){
@@ -1885,6 +1909,26 @@ namespace blogi {
            }
        }

        // Runs for the plugin's whole lifetime, independent of request
        // traffic, so orphaned getimage streams get their pooled mediadb
        // connection back within STREAM_IDLE_TIMEOUT even during a lull
        // (no new stream to piggyback the opportunistic sweep in
        // _storeStreamState() on). Woken early by the destructor via
        // _reaperCv so shutdown doesn't wait out a full sleep interval.
        void _reaperLoop(){
            std::unique_lock<std::mutex> lk(_reaperMtx);
            while(!_reaperStop){
                _reaperCv.wait_for(lk, std::chrono::seconds(5), [this]{ return _reaperStop; });
                if(_reaperStop) break;
                lk.unlock();
                {
                    std::unique_lock<std::mutex> slock(_streamMutex);
                    _reapStaleStreamsLocked();
                }
                lk.lock();
            }
        }

        void _storeStreamState(libhttppp::HttpRequest &req,
                               CheckoutPool<libhttppp::HttpClient>::Handle client,
                               size_t sendSize, int tid){
@@ -1991,6 +2035,10 @@ namespace blogi {
        std::mutex _mdbSetupMutex;
        std::mutex _streamMutex;
        std::map<uintptr_t, StreamState> _streams;
        std::thread _reaperThread;
        std::mutex _reaperMtx;
        std::condition_variable _reaperCv;
        bool _reaperStop = false;

        // ---- thread-safe resources for the offloadable getimage route ----