drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.44k stars 1.1k forks source link

newTransactionCoro() twice one one concurrent or too close making a memory stackoverflow #1630

Closed drinkmilkcream closed 1 year ago

drinkmilkcream commented 1 year ago

problem: on windows or debian when running app().getFastRedisClient()->newTransactionCoro(); twice in one concurrent or too closing in time occur(Parallel) a memory overflow in line 84 ,position below:

    void resume() const {
        __builtin_coro_resume(_Ptr);
    }

i first found this problem i haved put two newTransactionCoro in one program block below,just single line,but when i using Apache for press testing it random broken in line 84,so i put this two line together below as a demotion below:

i am appreciated for anyone's help,thanks a lot!!! it is emergency!

a simple demo: broken in “ auto transaction = co_await app().getFastRedisClient()->newTransactionCoro();” call second time below all the time cpp

#include "testRedis.h"
#include <drogon/nosql/RedisClient.h>
Task<HttpResponsePtr> testRedis::test(HttpRequestPtr req)
{
    auto resp = HttpResponse::newHttpResponse();
            {
                auto transaction = co_await app().getFastRedisClient()->newTransactionCoro();
                co_await transaction->execCommandCoro("set key 1");
                co_await transaction->execCommandCoro("expire key 10");
                co_await transaction->executeCoro();
            }
            {
               //here is where collapsing!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                auto transaction = co_await app().getFastRedisClient()->newTransactionCoro();
                co_await transaction->execCommandCoro("set key 1");
                co_await transaction->execCommandCoro("expire key 10");
                co_await transaction->executeCoro();
            }
            resp->setBody("");

    co_return resp;
}

h

 #pragma once

#include <drogon/HttpController.h>
#include <drogon/drogon.h>
#include <drogon/orm/DbClient.h>

using namespace drogon;
using namespace drogon::orm;

class testRedis : public HttpController<testRedis>
{
public:
    Task<HttpResponsePtr> test(HttpRequestPtr req);

    METHOD_LIST_BEGIN
        ADD_METHOD_TO(testRedis::test, "/test", HttpMethod::Get);
    METHOD_LIST_END
};

main

int main(int argc, char** argv)
{
    try
    {
#ifdef _WIN32
        app().loadConfigFile("./config/config.json").run();
#else
        app().loadConfigFile("/root/config/config.json").run();
#endif 
    }
    catch (std::exception& e)
    {
        LOG(INFO) << e.what();
    }
    return 0;
}

json

  "listeners": [
    {
      "address": "0.0.0.0",
      "port": 80
    }
  ],
  "redis_clients": [
    {
      "host": "192.168.110.88",
      "port": 6379,
      "passwd": "",
      "db": 0,
      "is_fast": true,
      "number_of_connections":1,
      "timeout": -1.0
    }
  ]
}
hwc0919 commented 1 year ago

working on it