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

deb

parent be56eb76
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
mediadb (20260422+66) unstable; urgency=low

  * Fix segfault in PrefetchBuffer (use-after-free):
    - Add destructor that waits for all in-flight io_pool futures
      before PrefetchBuffer members are destroyed.
    - Change lambda captures from `this` to by-value copies of db,
      cache, and media_id so tasks remain safe if PrefetchBuffer
      is destroyed while they are still queued or running.

 -- Jan Koester <jan.koester@tuxist.de>  Tue, 22 Apr 2026 00:00:00 +0200

mediadb (20260422+65) unstable; urgency=low

  * Fix HTTP timeouts on /raw and /preview endpoints:
+25 −3
Original line number Diff line number Diff line
@@ -41,6 +41,17 @@ struct PrefetchBuffer {
    };
    std::deque<PendingBlock> ring;

    ~PrefetchBuffer() {
        // Wait for all in-flight io_pool tasks before destroying members
        // they reference (db, media_id, cache).  Destroying a std::future
        // does NOT block, so without this the tasks would access freed memory.
        for (auto& b : ring) {
            if (b.fut.valid()) {
                try { b.fut.wait(); } catch (...) {}
            }
        }
    }

    static std::string make_key(const std::string& mid, std::uint64_t off, std::uint64_t len) {
        return "prefetch:" + mid + ":" + std::to_string(off) + ":" + std::to_string(len);
    }
@@ -79,11 +90,22 @@ struct PrefetchBuffer {
                p.set_value(cached);
                ring.push_back(PendingBlock{off, len, p.get_future(), std::vector<uint8_t>()});
            } else {
                // Capture members by value — not `this` — so the lambda
                // remains safe even if PrefetchBuffer is destroyed while
                // the task is still queued / running in io_pool.
                MediaBackendApi* pdb = db;
                BlobCache* pcache = cache;
                std::string pmid = media_id;
                ring.push_back(PendingBlock{
                    off, len,
                    io_pool->submit([this, off, len]() {
                        auto bytes = db->read_media_data_range(media_id, off, len);
                        cache_put(off, len, bytes);
                    io_pool->submit([pdb, pcache, pmid, off, len]() {
                        auto bytes = pdb->read_media_data_range(pmid, off, len);
                        if (pcache && !bytes.empty()) {
                            BlobValue bv;
                            bv.data = bytes;
                            bv.type = BlobType::prefetch;
                            pcache->put(make_key(pmid, off, len), std::move(bv));
                        }
                        return bytes;
                    }),
                    std::vector<uint8_t>()