Commit d2722797 authored by jan.koester's avatar jan.koester
Browse files

tset

parent 77b40ba1
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
mediadb (20260419+25) unstable; urgency=critical

  * Fix preview render queue lock-up where an exception thrown during 
    FFmpeg initialization would jump the stack and skip the lock release 
    on the `inflight_mutex_`, permanently deadlocking duplicate preview 
    requests with a "timeout waiting for in-flight preview" error.

 -- Jan Koester <jan.koester@tuxist.de>  Sun, 19 Apr 2026 14:00:00 +0200

mediadb (20260419+24) unstable; urgency=critical

  * Fix broken cluster fetch and index replication operations on startup: Add 
+15 −17
Original line number Diff line number Diff line
@@ -699,18 +699,28 @@ std::shared_ptr<const BlobValue> PreviewService::get_or_create_streaming(const M
        inflight_.insert(key);
    }

    struct InflightGuard {
        PreviewService* self;
        std::string key;
        ~InflightGuard() {
            std::lock_guard<std::mutex> lk(self->inflight_mutex_);
            self->inflight_.erase(key);
            self->inflight_cv_.notify_all();
        }
    } inflight_guard{this, key};

    // Acquire render semaphore with timeout — limits concurrent FFmpeg
    // processes to avoid overloading the CPU.
    if (!render_sem_.try_acquire_for(std::chrono::seconds(30))) {
        {
            std::lock_guard<std::mutex> lk(inflight_mutex_);
            inflight_.erase(key);
        }
        inflight_cv_.notify_all();
        error_out = "preview render queue full (semaphore timeout)";
        return nullptr;
    }

    struct SemGuard {
        PreviewService* self;
        ~SemGuard() { self->render_sem_.release(); }
    } sem_guard{this};

    // Run FFmpeg on the io_pool with a timeout.  This prevents a stuck
    // FFmpeg render from blocking the HTTP worker thread indefinitely.
    // Captures are by value so the lambda is safe if we return on timeout.
@@ -727,14 +737,8 @@ std::shared_ptr<const BlobValue> PreviewService::get_or_create_streaming(const M
    });

    auto status = fut.wait_for(std::chrono::seconds(60));
    render_sem_.release();

    if (status == std::future_status::timeout) {
        {
            std::lock_guard<std::mutex> lk(inflight_mutex_);
            inflight_.erase(key);
        }
        inflight_cv_.notify_all();
        error_out = "preview render timed out after 60s";
        return nullptr;
    }
@@ -742,12 +746,6 @@ std::shared_ptr<const BlobValue> PreviewService::get_or_create_streaming(const M
    auto [result, render_err] = fut.get();
    error_out = std::move(render_err);

    {
        std::lock_guard<std::mutex> lk(inflight_mutex_);
        inflight_.erase(key);
    }
    inflight_cv_.notify_all();

    if (!result.has_value()) {
        return nullptr;
    }