Как запустить мой простой http-сервер в качестве демона / службы? - PullRequest
0 голосов
/ 11 октября 2019

Вот мой крошечный http-сервер, основанный на libevent;

#include "fmt/format.h"
#include <cstdint>
#include <cstdio>
#include <event2/event-config.h>
#include <event2/util.h>
#include <evhttp.h>
#include <memory>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <type_traits>
#include <unistd.h>
auto
main() -> int
{
    constexpr char host[] = "127.0.0.1";
    constexpr std::uint16_t port = 5555;

    using event_base_new_type
        = std::pointer_traits<decltype(event_base_new())>::element_type;
    using event_base_deleter_type = decltype(&event_base_free);
    auto event_base
        = std::unique_ptr<event_base_new_type, event_base_deleter_type>(
            event_base_new(), &event_base_free);

    if(!(event_base))
    {
        fmt::print(stderr, "Failed to init libevent.\n");
        return -1;
    }

    using evhttp_new_type = std::pointer_traits<decltype(
        evhttp_new(event_base.get()))>::element_type;
    using evhttp_deleter_type = decltype(&evhttp_free);
    auto http = std::unique_ptr<evhttp_new_type, evhttp_deleter_type>(
        evhttp_new(event_base.get()), &evhttp_free);

    auto handle = evhttp_bind_socket_with_handle(http.get(), host, port);
    if(!handle)
    {
        fmt::print(stderr, "Failed to init http server.\n");
        return -1;
    }
    auto callback = [](evhttp_request* req, void*) {
        auto* OutBuf = evhttp_request_get_output_buffer(req);
        if(!OutBuf)
            return;
        evbuffer_add_printf(OutBuf,
            "<html><body><center><h1>Hello World!</h1></center></body></html>");
        evhttp_send_reply(req, HTTP_OK, "", OutBuf);
    };
    evhttp_set_gencb(http.get(), callback, nullptr);

    if(event_base_dispatch(event_base.get()) == -1)
    {
        fmt::print(stderr, "Failed to run messahe loop.\n");
        return -1;
    }


    return 0;
}
  • Компиляция: g++ a.cpp -lfmt -levent
  • run: ./a.out
  • browser: http://127.0.0.1:5555

Я пытаюсь запустить эту программу как демон, чтобы я мог включить ее в свои тестовые сценарии ctest.

Я пробовал эту эту статью , вот мой код:

#include "fmt/format.h"
#include <cstdint>
#include <cstdio>
#include <event2/event-config.h>
#include <event2/util.h>
#include <evhttp.h>
#include <memory>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <type_traits>
#include <unistd.h>
static void
skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if(pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if(pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if(setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    // TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if(pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if(pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for(x = sysconf(_SC_OPEN_MAX); x >= 0; x--)
    {
        close(x);
    }

    /* Open the log file */
    openlog("firstdaemon", LOG_PID, LOG_DAEMON);
}

auto
main() -> int
{
    constexpr char host[] = "127.0.0.1";
    constexpr std::uint16_t port = 5555;

    using event_base_new_type
        = std::pointer_traits<decltype(event_base_new())>::element_type;
    using event_base_deleter_type = decltype(&event_base_free);
    auto event_base
        = std::unique_ptr<event_base_new_type, event_base_deleter_type>(
            event_base_new(), &event_base_free);

    if(!(event_base))
    {
        fmt::print(stderr, "Failed to init libevent.\n");
        return -1;
    }

    using evhttp_new_type = std::pointer_traits<decltype(
        evhttp_new(event_base.get()))>::element_type;
    using evhttp_deleter_type = decltype(&evhttp_free);
    auto http = std::unique_ptr<evhttp_new_type, evhttp_deleter_type>(
        evhttp_new(event_base.get()), &evhttp_free);

    auto handle = evhttp_bind_socket_with_handle(http.get(), host, port);
    if(!handle)
    {
        fmt::print(stderr, "Failed to init http server.\n");
        return -1;
    }
    auto callback = [](evhttp_request* req, void*) {
        auto* OutBuf = evhttp_request_get_output_buffer(req);
        if(!OutBuf)
            return;
        evbuffer_add_printf(OutBuf,
            "<html><body><center><h1>Hello World!</h1></center></body></html>");
        evhttp_send_reply(req, HTTP_OK, "", OutBuf);
    };
    evhttp_set_gencb(http.get(), callback, nullptr);

    skeleton_daemon();
    while(1)
    {
        // TODO: Insert daemon code here.
        if(event_base_dispatch(event_base.get()) == -1)
        {
            fmt::print(stderr, "Failed to run messahe loop.\n");
            return -1;
        }

        syslog(LOG_NOTICE, "First daemon started.");
        sleep(1000);
        break;
    }

    syslog(LOG_NOTICE, "First daemon terminated.");
    closelog();


    return 0;
}

Но «Привет мир» не может быть отображен. Как исправить или есть более приятное решение?

...