aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/util/signalhandler.cpp
blob: 6bc7fcd17df18dcb87694641d61084f2d1ee17ce (plain) (blame)
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
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "signalhandler.h"
#include <cassert>

namespace vespalib {

std::vector<SignalHandler*> SignalHandler::_handlers;

namespace {

class Shutdown
{
public:
    ~Shutdown() {
        SignalHandler::shutdown();
    }
};

}

// Clear SignalHandler::_handlers in a slightly less unsafe manner.
Shutdown shutdown;

SignalHandler SignalHandler::HUP(SIGHUP);
SignalHandler SignalHandler::INT(SIGINT);
SignalHandler SignalHandler::TERM(SIGTERM);
SignalHandler SignalHandler::PIPE(SIGPIPE);
SignalHandler SignalHandler::SEGV(SIGSEGV);
SignalHandler SignalHandler::ABRT(SIGABRT);
SignalHandler SignalHandler::BUS(SIGBUS);
SignalHandler SignalHandler::ILL(SIGILL);
SignalHandler SignalHandler::TRAP(SIGTRAP);
SignalHandler SignalHandler::FPE(SIGFPE);
SignalHandler SignalHandler::QUIT(SIGQUIT);
SignalHandler SignalHandler::USR1(SIGUSR1);

void
SignalHandler::handleSignal(int signal)
{
    if ((((size_t)signal) < _handlers.size()) && (_handlers[signal] != 0)) {
        _handlers[signal]->gotSignal();
    }
}

void
SignalHandler::gotSignal()
{
    _gotSignal = 1;
}

SignalHandler::SignalHandler(int signal)
    : _signal(signal),
      _gotSignal(0)
{
    assert(signal >= 0);
    while (_handlers.size() < ((size_t)(signal + 1))) {
        _handlers.push_back(0);
    }
    assert(_handlers[signal] == 0);
    _handlers[signal] = this;
}

void
SignalHandler::hook()
{
    struct sigaction act;
    act.sa_handler = handleSignal;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(_signal, &act, nullptr);
}

void
SignalHandler::ignore()
{
    struct sigaction act;
    act.sa_handler = SIG_IGN;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(_signal, &act, nullptr);
}

bool
SignalHandler::check() const
{
    return (_gotSignal != 0);
}

void
SignalHandler::clear()
{
    _gotSignal = 0;
}

void
SignalHandler::unhook()
{
    struct sigaction act;
    act.sa_handler = SIG_DFL;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(_signal, &act, nullptr);
}


void
SignalHandler::shutdown()
{
    for (std::vector<SignalHandler*>::iterator
             it = _handlers.begin(), ite = _handlers.end();
         it != ite;
         ++it) {
        if (*it != nullptr)
            (*it)->unhook();
    }
    std::vector<SignalHandler *>().swap(_handlers);
}

} // vespalib