Cylix / cpp_redis

C++11 Lightweight Redis client: async, thread-safe, no dependency, pipelining, multi-platform - NO LONGER MAINTAINED - Please check https://github.com/cpp-redis/cpp_redis
MIT License
1.24k stars 551 forks source link

cpp_redis::client causes program to crash #156

Open cblauvelt opened 6 years ago

cblauvelt commented 6 years ago

I'm attempting to run a variation of your example program and I cannot seem to get it to run without crashing.

I am running the program below:

#include <iostream>
#include <cpp_redis/cpp_redis>

using namespace std;
int main() {
    cpp_redis::client client;
    cpp_redis::active_logger = make_unique<cpp_redis::logger>(cpp_redis::logger::log_level::debug);

    client.connect("127.0.0.1", 6379, [&](const std::string& host, std::size_t port, cpp_redis::client::connect_state status) {
        if (status == cpp_redis::client::connect_state::dropped) {
        cout << "client disconnected from " <<  host << ":" << port << endl;
        } else if (status == cpp_redis::client::connect_state::ok) {
            cout << "client connected to " <<  host << ":" << port << endl;
        }
    });

    // same as client.send({ "SET", "hello", "42" }, ...)
    client.set("hello", "42", [](cpp_redis::reply& reply) {
        std::cout << "set hello 42: " << reply << std::endl;
        // if (reply.is_string())
        //   do_something_with_string(reply.as_string())
    });

    // same as client.send({ "GET", "hello" }, ...)
    client.get("hello", [](cpp_redis::reply& reply) {
        std::cout << "get hello: " << reply << std::endl;
        // if (reply.is_string())
        //   do_something_with_string(reply.as_string())
    });

    // synchronous commit, no timeout
    client.sync_commit();

    // same as client.send({ "DECRBY", "hello", 12 }, ...)
    client.decrby("hello", 12, [](cpp_redis::reply& reply) {
        std::cout << "decrby hello 12: " << reply << std::endl;
        // if (reply.is_integer())
        //   do_something_with_integer(reply.as_integer())
    });

    // same as client.send({ "GET", "hello" }, ...)
    client.get("hello", [](cpp_redis::reply& reply) {
        std::cout << "get hello: " << reply << std::endl;
        // if (reply.is_string())
        //   do_something_with_string(reply.as_string())
    });

    // commands are pipelined and only sent when client.commit() is called
    // client.commit();

    // synchronous commit, no timeout
    client.sync_commit();

    // synchronous commit, timeout
    // client.sync_commit(std::chrono::milliseconds(100));
}
and my output is:
[DEBUG][cpp_redis][/opt/projects/src/sources/core/client.cpp:93] cpp_redis::client attempts to connect
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:59] cpp_redis::network::redis_connection attempts to connect
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:69] cpp_redis::network::redis_connection connected
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:111] cpp_redis::client connected
client connected to 127.0.0.1:6379
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:171] cpp_redis::client attemps to store new command in the send buffer
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:113] cpp_redis::network::redis_connection stored new command in the send buffer
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:173] cpp_redis::client stored new command in the send buffer
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:171] cpp_redis::client attemps to store new command in the send buffer
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:113] cpp_redis::network::redis_connection stored new command in the send buffer
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:173] cpp_redis::client stored new command in the send buffer
[DEBUG][cpp_redis][/opt/projects/src/sources/core/client.cpp:214] cpp_redis::client attempts to send pipelined commands
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:124] cpp_redis::network::redis_connection attempts to send pipelined commands
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:136] cpp_redis::network::redis_connection sent pipelined commands
[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:216] cpp_redis::client sent pipelined commands
[DEBUG][cpp_redis][/opt/projects/src/sources/core/client.cpp:205] cpp_redis::client waiting for callbacks to complete
The terminal process terminated with exit code: 1

I am compiling this with: -DCMAKE_BUILD_TYPE=Release -DLOGGING_ENABLED=1

As you can see from the output, it's crashing while waiting for the call_backs to complete. This also occurs if all the code within the callbacks is commented out.

Please let me know if you need any additional information.

cblauvelt commented 6 years ago

I took out all the set and get requests and only left the client.sync_commit();

The output now gets to disconnecting the connection but it fails during the disconnect. This may imply it's a tacopie issue.

Output is below:

[INFO ][cpp_redis][/opt/projects/src/sources/core/client.cpp:216] cpp_redis::client sent pipelined commands
[DEBUG][cpp_redis][/opt/projects/src/sources/core/client.cpp:205] cpp_redis::client waiting for callbacks to complete
[DEBUG][cpp_redis][/opt/projects/src/sources/core/client.cpp:207] cpp_redis::client finished waiting for callback completion
[DEBUG][cpp_redis][/opt/projects/src/sources/network/redis_connection.cpp:82] cpp_redis::network::redis_connection attempts to disconnect
The terminal process terminated with exit code: 1

The code executed after this line is:

//! close connection
  m_client->disconnect(wait_for_removal);

  //! clear buffer
  m_buffer.clear();

  __CPP_REDIS_LOG(debug, "cpp_redis::network::redis_connection disconnected");
Cylix commented 6 years ago

Hi @cblauvelt ,

Sorry to hear you encountered an issue while using cpp_redis.

I tried your example on my side using the same flags, except that I compiled in C++11 (seems you compiled in C++14 in order to use std::make_unique?). On my side, the program runs fine and returns the right output.

May I know which version of cpp_redis are you using? Are you using the tacopie version that comes with the library or a different version? What is your programming environment (system / compiler / any other relevant information)?

Thanks

cblauvelt commented 6 years ago

Thank you for the quick reply.

I created a docker image that should allow you to see the error. I am actually using C++17.

I compiled the cpp_redis source using the following commands:

git clone https://github.com/Cylix/cpp_redis.git
cd cpp_redis
git submodule init && git submodule update
docker container run -i --rm --name builder -v ${PWD}:/opt/projects/src:ro -v build:/opt/projects/build cblauvelt/cpp17dev ./cmakeit -DCMAKE_BUILD_TYPE=debugfull -DLOGGING_ENABLED=1

Then from my directory in 'c:\projects\playground\cpp-redis\client\' I executed the following:

docker container run -i --rm --name builder -v c:\projects\playground\cpp-redis\client:/opt/projects/src:ro -v c:\projects\playground\cpp-redis\client/build:/opt/projects/build -v /C/projects/cpp_redis/includes/cpp_redis:/usr/include/cpp_redis:ro -v /C/projects/tacopie/includes/tacopie:/usr/include/tacopie:ro -v /C/projects/cpp_redis/build/lib:/usr/lib/cpp_redis:ro cblauvelt/cpp17dev-ubuntu ./cmakeit -DCMAKE_BUILD_TYPE=debugfull

Start redis:

docker container run -d --rm --name redis -p 6379:6379 redis:4.0-alpine

Run client program:

docker container run -i --rm -v c:\projects\playground\cpp-redis\client/build/:/opt/projects/build --name cpp-redis-client --net=host pygmy/alpine-tini:latest /opt/projects/build/cpp-redis-client

Below is my CMakeLists.txt file for your reference:

cmake_minimum_required(VERSION 3.9)
project(cpp-redis-client)

# define project variables
set(TARGET_NAME ${PROJECT_NAME})

if(${UNIX})
    message("Setting up for Unix Environment")

    set( THREAD_CXX_FLAGS "-pthread")

    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${THREAD_CXX_FLAGS}" )

    find_library(CPP_REDIS_LIB_PATH NAMES "cpp_redis" PATHS "/usr/lib/cpp_redis")
    find_library(TACOPIE_LIB_PATH NAMES "tacopie" PATHS "/usr/lib/cpp_redis")

    add_definitions( "-DASIO_STANDALONE" )

    include_directories("vendor" ${CMAKE_SOURCE_DIR})

    # Set optimization strategy
    if(${OPTIMIZE_FOR_SIZE})
        message("Optimizing for size.")
        set( OPTIMIZE_FLAGS "-Os")
    else(${OPTIMIZE_FOR_SIZE})
        message("Optimizing for speed.")
        set( OPTIMIZE_FLAGS "-O3")
    endif(${OPTIMIZE_FOR_SIZE})

    set(CMAKE_EXE_LINKER_FLAGS "-static")

else(${UNIX})
    message( FATAL_ERROR "Non-unix build is not supported. Feel free to add one.")

endif(${UNIX})

set(SOURCE_FILES
    main.cpp
)

include_directories( "${CMAKE_SOURCE_DIR}/vendor" )

add_executable(${TARGET_NAME} ${SOURCE_FILES})

link_directories(${CPP_REDIS_LIB_PATH})

target_link_libraries(${TARGET_NAME} ${CPP_REDIS_LIB_PATH} ${TACOPIE_LIB_PATH})
Cylix commented 6 years ago

Awesome, I'll try that ASAP and let you know when I got fresh news about this issue!

Cylix commented 6 years ago

Just note to myself: someone reported me by email an issue on tacopie due to concurrency if the tcp client is disconnected while reading or writing (connection closed by remote server). In such case, the client is disconnected without waiting for io_service callback cleanup and the reading or writing callback might executed right after the client is destroyed. This may be related and possibly fix by the incoming tacopie fix.

lvpidadiao commented 6 years ago

hi, are you still getting on with this issue?

cblauvelt commented 6 years ago

Yes. I cannot figure out what the problem is.

On Mon, Mar 19, 2018 at 2:52 AM, lvpidadiao notifications@github.com wrote:

hi, are you still getting on with this issue?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Cylix/cpp_redis/issues/156#issuecomment-374116726, or mute the thread https://github.com/notifications/unsubscribe-auth/AB-LqqrOcWZNS143WwXl1sKJAstTuwAxks5tf1WjgaJpZM4Rv4qm .