File: http_server_shutdown.cc

package info (click to toggle)
pistache 0.4.26%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,484 kB
  • sloc: cpp: 29,406; ansic: 1,190; sh: 510; makefile: 17
file content (145 lines) | stat: -rw-r--r-- 3,462 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * SPDX-FileCopyrightText: 2019 Oleg Burchakov
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "pistache/endpoint.h"
#include <signal.h>

#ifdef _WIN32
#include <Windows.h>
#include <WinCon.h>
// #include <ConsoleApi.h> // included in WinCon.h; needs Kernel32.lib
#endif

using namespace Pistache;

class HelloHandler : public Http::Handler
{
public:
    HTTP_PROTOTYPE(HelloHandler)

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

#ifdef _WIN32

static std::atomic<bool> lSigBool = false;
static std::mutex lMutex;
static std::condition_variable cv;

#define CTRL_TYPE_EMPTY 0xDEADDEAD
static DWORD lCtrlType = CTRL_TYPE_EMPTY;
static BOOL consoleCtrlHandler(DWORD dwCtrlType)
{
    std::unique_lock<std::mutex> lock(lMutex);
    if (lCtrlType == 0)
    {
        lCtrlType = dwCtrlType;

        lSigBool = true;
        cv.notify_one();
    }

    return(TRUE);// We have handled the ctrl signal
}

#endif // of ifdef _WIN32

int main()
{
#ifdef _WIN32
    // Note: SetConsoleCtrlHandler can be used for console apps or GUI apps;
    // for GUI apps, the notification from WM_QUERYENDSESSION _may_ arrive
    // before the call to consoleCtrlHandler

    BOOL set_cch_res = SetConsoleCtrlHandler(consoleCtrlHandler,
                                             true /*Add*/);
    if (!set_cch_res)
    {
        perror("install ctrl-c-handler failed");
        return 1;
    }

#else
    sigset_t signals;
    if (sigemptyset(&signals) != 0
        || sigaddset(&signals, SIGTERM) != 0
        || sigaddset(&signals, SIGINT) != 0
        || sigaddset(&signals, SIGHUP) != 0
        || pthread_sigmask(SIG_BLOCK, &signals, nullptr) != 0)
    {
        perror("install signal handler failed");
        return 1;
    }
#endif

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

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

#ifdef _WIN32
    std::unique_lock<std::mutex> lock(lMutex);
    cv.wait(lock, [&] {return(lSigBool.load());});

    switch(lCtrlType)
    {
    case CTRL_TYPE_EMPTY:
        perror("ctrl-type not set");
        break;

    case CTRL_C_EVENT:
        std::cout <<
            "ctrl-c received from keyboard or GenerateConsoleCtrlEvent" <<
            std::endl;
        break;

    case CTRL_BREAK_EVENT:
        std::cout <<
            "ctrl-break received from keyboard or GenerateConsoleCtrlEvent" <<
            std::endl;
        break;

    case CTRL_CLOSE_EVENT:
        std::cout <<
            "Attached console closed" << std::endl;
        break;

    case CTRL_LOGOFF_EVENT:
        std::cout <<
            "User logging off" << std::endl;
        break;

    case CTRL_SHUTDOWN_EVENT:
        std::cout <<
            "System shutting down" << std::endl;
        break;

    default:
        perror("ctrl-type unknown");
        break;
    }
#else // not ifdef _WIN32
    int signal = 0;
    int status = sigwait(&signals, &signal);
    if (status == 0)
    {
        std::cout << "received signal " << signal << std::endl;
    }
    else
    {
        std::cerr << "sigwait returns " << status << std::endl;
    }
#endif // of ifdef _WIN32... else...

    server.shutdown();
}