Commit 9312c702 authored by jan.koester's avatar jan.koester
Browse files

test

parent f57636b6
Loading
Loading
Loading
Loading
+31 −2
Changes for src/blogi.cpp: 31 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ blogi::Blogi::Blogi(std::vector<netplus::socket *> serversocket, bool debug)
#endif
            }
        }
        ctx.plgArgs->dbMutex = std::vector<std::mutex>(ctx.plgArgs->database.size());

        std::unique_ptr<dbpp::ReplicatedDatabase> initdb = std::make_unique<dbpp::ReplicatedDatabase>(dcfg.dbDriver, dcfg.dbConnection);
        for (const auto &rep : dcfg.dbReplicas)
@@ -531,6 +532,7 @@ bool blogi::Blogi::reloadConfig()
                std::cerr << "[blogi] Reload: DB connect failed for '" << dcfg.names[0] << "': " << e.what() << std::endl;
                continue;
            }
            ctx->plgArgs->dbMutex = std::vector<std::mutex>(ctx->plgArgs->database.size());

            std::unique_ptr<dbpp::ReplicatedDatabase> initdb = std::make_unique<dbpp::ReplicatedDatabase>(dcfg.dbDriver, dcfg.dbConnection);
            for (const auto &rep : dcfg.dbReplicas)
@@ -3048,13 +3050,19 @@ void blogi::Blogi::RequestEvent(libhttppp::HttpRequest &curreq, const int tid, U
        libhttppp::HttpResponse curres;
        std::string sessid;
        libhtmlpp::HtmlElement index;
        Session sess(*PlgArgs->database[tid]);

        if (curreq.isMobile())
            index = ctx->mIndex;
        else
            index = ctx->index;

        {
            // database[tid] is only safe for one thread at a time (see the
            // dbMutex comment in plugin.h) — an offloaded /media/getimage/
            // stream sharing this tid with another one on the same H2
            // connection would otherwise race here on every request.
            std::lock_guard<std::mutex> dbLock(PlgArgs->dbMutex[tid]);
            Session sess(*PlgArgs->database[tid]);
            try
            {
                cookie.parse(curreq);
@@ -3124,6 +3132,7 @@ void blogi::Blogi::RequestEvent(libhttppp::HttpRequest &curreq, const int tid, U
                    return;
                }
            }
        }

        try
        {
@@ -3431,7 +3440,11 @@ void blogi::Blogi::RequestEvent(libhttppp::HttpRequest &curreq, const int tid, U
                }

                libhtmlpp::HtmlString output;
                std::string _lang = blogi::getLang(*PlgArgs->database[tid]);
                std::string _lang;
                {
                    std::lock_guard<std::mutex> dbLock(PlgArgs->dbMutex[tid]);
                    _lang = blogi::getLang(*PlgArgs->database[tid]);
                }
                libhtmlpp::HtmlString err;
                err << "<div id=\"content\">"
                    << "<span>" << blogi::tr(_lang, "Page or content not found") << "</span><br/>"
@@ -3460,9 +3473,17 @@ void blogi::Blogi::RequestEvent(libhttppp::HttpRequest &curreq, const int tid, U
        }
        catch (libhttppp::HTTPException &e)
        {
            bool shouldRetry = false;
            {
                std::lock_guard<std::mutex> dbLock(PlgArgs->dbMutex[tid]);
                if (!PlgArgs->database[tid]->isConnected() && retries < MAX_RETRIES)
                {
                    PlgArgs->database[tid]->reset();
                    shouldRetry = true;
                }
            }
            if (shouldRetry)
            {
                ++retries;
                goto RETRY_REQUEST;
            }
@@ -3470,10 +3491,18 @@ void blogi::Blogi::RequestEvent(libhttppp::HttpRequest &curreq, const int tid, U
        }
        catch (std::exception &e)
        {
            bool shouldRetry = false;
            {
                std::lock_guard<std::mutex> dbLock(PlgArgs->dbMutex[tid]);
                if (!PlgArgs->database[tid]->isConnected() && retries < MAX_RETRIES)
                {
                    std::cerr << "RequestEvent: DB connection lost (" << e.what() << "), reconnecting (attempt " << retries + 1 << "/" << MAX_RETRIES << ")" << std::endl;
                    PlgArgs->database[tid]->reset();
                    shouldRetry = true;
                }
            }
            if (shouldRetry)
            {
                ++retries;
                goto RETRY_REQUEST;
            }
+11 −0
Changes for src/plugin.h: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#include <memory>
#include <map>
#include <mutex>
#include <vector>
#include <chrono>
#include <optional>
@@ -94,6 +95,16 @@ namespace blogi {

    struct PluginArgs{
        std::vector<std::unique_ptr<dbpp::ReplicatedDatabase>> database;
        // database[tid] was only ever safe to touch because exactly one
        // thread used a given tid at a time. The H2 offload pool (see
        // Blogi::shouldOffloadH2Dispatch) breaks that invariant for
        // requests handled on it — e.g. two /media/getimage/ streams
        // multiplexed on the same HTTP/2 connection share the connection's
        // tid and can run concurrently on different pool threads. Guards
        // any direct database[tid] access reachable from that path
        // (RequestEvent's session/cookie-consent handling); one mutex per
        // tid so unrelated tids/connections never contend.
        std::vector<std::mutex>                                      dbMutex;
        std::unique_ptr<Auth>                                         auth;
        std::unique_ptr<Theme>                                      theme;
        std::unique_ptr<SmtpSettings>                           smtp;