pistache icon indicating copy to clipboard operation
pistache copied to clipboard

run_http_server example throws runtime_exception

Open carun opened this issue 7 years ago • 9 comments

So the example was running earlier and I killed it a few times with kill -9 (as I didn't know how to stop the server). After that when I ran the example, I got the runtime_error

10:57:16 AIM-ES ~/code/cpp/pistache-master/b
$ examples/run_http_server
Cores = 8
Using 2 threads
terminate called after throwing an instance of 'std::runtime_error'
  what():  epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev): Bad file descriptor
Aborted (core dumped)
10:57:22 AIM-ES ~/code/cpp/pistache-master/b
$

carun avatar May 09 '18 17:05 carun

Hello.

Yes, this is a known issue when you kill it and start it again right after. The fd that is returned by the listener is in a bad state and can not be added in the event-loop.

For now, the workaround is just to wait a little bit before restarting. It'll get fixed eventually as it's also annoying me when debugging.

oktal avatar May 27 '18 17:05 oktal

Annoyingly, "a little bit" seems to be over 1 min 30 sec when it happens, though it definitely doesn't happen all the time. If in production the server had to be restarted and something like this happens, it could cause major problems and frustrations for users.

jeffvandyke avatar Jun 01 '18 12:06 jeffvandyke

Any news on that? Or any workarounds?

MasterGroosha avatar Mar 22 '19 12:03 MasterGroosha

@MasterGroosha Do you have the reproduction of this bug on latest sources?

knowledge4igor avatar Mar 22 '19 20:03 knowledge4igor

@knowledge4igor Sorry for the late reply, I had to get to work to test something. I have two examples. The first one works fine and closes correctly on Ctrl+C when launched from terminal inside Visual Studio Code.

#include "pistache/endpoint.h"

using namespace Pistache;

class HelloHandler : public Http::Handler {
public:

    HTTP_PROTOTYPE(HelloHandler) 

    void onRequest(const Http::Request& request, Http::ResponseWriter response) override{
        UNUSED(request);
        response.send(Pistache::Http::Code::Ok, "Hello World\n");
    }
};

int main() {
    Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(9080));
    auto opts = Pistache::Http::Endpoint::options()
        .threads(2);

    Http::Endpoint server(addr); 
    server.init(opts);
    server.setHandler(Http::make_handler<HelloHandler>());
    server.serve();

    server.shutdown();
}

However this code cannot be closed with Ctrl+C, only with Ctrl+Z and kill -9 afterwards:

#include <algorithm>
#include <pistache/http.h>
#include <pistache/http_headers.h>
#include <pistache/router.h>
#include <pistache/endpoint.h>

using namespace std;
using namespace Pistache;

volatile int need_stop = 1;

namespace Generic {

    void handleReady(const Rest::Request&, Http::ResponseWriter response) {
        response.send(Http::Code::Ok, "OK\n");
    }

    void shutdown(const Rest::Request&, Http::ResponseWriter response) {
        need_stop = 0;
        response.send(Http::Code::Ok, "Stopping server\n");
    }
}

class StatsEndpoint {
public:
    StatsEndpoint(Address addr)
        : httpEndpoint(std::make_shared<Http::Endpoint>(addr))
    { }

    void init(size_t thr = 2) {
        auto opts = Http::Endpoint::options()
            .threads(thr)
            .flags(Tcp::Options::InstallSignalHandler);
        httpEndpoint->init(opts);
        setupRoutes();
    }

    void start() {
        httpEndpoint->setHandler(router.handler());
        httpEndpoint->serve();
    }

    void shutdown() {
        httpEndpoint->shutdown();
    }

private:
    void setupRoutes() {
        using namespace Rest;

        Routes::Get(router, "/ready", Routes::bind(&Generic::handleReady));
        Routes::Get(router, "/shutdown", Routes::bind(&Generic::shutdown));
    }

    std::shared_ptr<Http::Endpoint> httpEndpoint;
    Rest::Router router;
};

int main(int argc, char *argv[]) {
    Port port(9084);

    int thr = 2;

    if (argc >= 2) {
        port = std::stol(argv[1]);

        if (argc == 3)
            thr = std::stol(argv[2]);
    }

    Address addr(Ipv4::any(), port);

    cout << "Cores = " << hardware_concurrency() << endl;
    cout << "Using " << thr << " threads" << endl;
    cout << "Running on port " << port << endl;

    StatsEndpoint stats(addr);

    stats.init(thr);
    stats.start();

    while(need_stop)
    {
        sleep(2);
    }
    std::cout << "Stopping server\n";
    stats.shutdown();
    std::cout << "Stopped\n";
    return 0;
}

The first code is taken directly from documentation, the second one is taken from docs as well, with small modifications (removed some handlers to reduce code). Environment: KDE Neon 18.04 running in VirtualBox. IDE: Visual Studio Code with cpp plugin. Pistache latest as of 22 March 2019.

MasterGroosha avatar Mar 25 '19 08:03 MasterGroosha

@MasterGroosha Hello, Evgeny, if I'm not mistaken you are writting about server shutdown scenario. I will definitely think about convenient API for this action. This bug is about runtime_exception during run_http_server binary execution. Do you have this problem?

knowledge4igor avatar Mar 25 '19 21:03 knowledge4igor

@knowledge4igor oh, my bad. I was talking about server not shutting down and throwing "address already in use" error due to bad descriptor. I guess this is wrong issue for my message. Sorry! Should I delete my messages?

MasterGroosha avatar Mar 25 '19 21:03 MasterGroosha

@MasterGroosha Everthing is ok, don't worry :)

knowledge4igor avatar Mar 25 '19 22:03 knowledge4igor

Has this bug been fixed? I'm having a similar issue and was wondering if there's been any updates on properly handling signals

benjamintli avatar Jun 19 '20 22:06 benjamintli