855b28b31721727cf1f431a918a251dc2e6a3dfc
[WebKit-https.git] / Source / WTF / wtf / threads / Signals.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "Signals.h"
28
29 #if USE(PTHREADS)
30
31 #include <cstdio>
32 #include <mutex>
33 #include <signal.h>
34 #include <wtf/Atomics.h>
35 #include <wtf/DataLog.h>
36 #include <wtf/LocklessBag.h>
37 #include <wtf/NeverDestroyed.h>
38
39 namespace WTF {
40
41 static LazyNeverDestroyed<LocklessBag<SignalHandler>> handlers[static_cast<size_t>(Signal::NumberOfSignals)] = { };
42 static struct sigaction oldActions[static_cast<size_t>(Signal::NumberOfSignals)];
43 static std::once_flag initializeOnceFlags[static_cast<size_t>(Signal::NumberOfSignals)];
44
45 static void jscSignalHandler(int sig, siginfo_t* info, void* mcontext)
46 {
47     Signal signal = fromSystemSignal(sig);
48
49     auto restoreDefault = [&] {
50         struct sigaction defaultAction;
51         defaultAction.sa_handler = SIG_DFL;
52         sigfillset(&defaultAction.sa_mask);
53         defaultAction.sa_flags = 0;
54         auto result = sigaction(sig, &defaultAction, nullptr);
55         dataLogLnIf(result == -1, "Unable to restore the default handler while proccessing signal ", sig, " the process is probably deadlocked. (errno: ", strerror(errno), ")");
56     };
57
58     // This shouldn't happen but we might as well be careful.
59     if (signal == Signal::Unknown) {
60         dataLogLn("We somehow got called for an unknown signal ", sig, ", halp.");
61         restoreDefault();
62         return;
63     }
64
65     bool didHandle = false;
66     bool restoreDefaultHandler = false;
67     handlers[static_cast<size_t>(signal)]->iterate([&] (const SignalHandler& handler) {
68         switch (handler(sig, info, mcontext)) {
69         case SignalAction::Handled:
70             didHandle = true;
71             break;
72         case SignalAction::ForceDefault:
73             restoreDefaultHandler = true;
74             break;
75         default:
76             break;
77         }
78     });
79
80     if (restoreDefaultHandler) {
81         restoreDefault();
82         return;
83     }
84
85     struct sigaction& oldAction = oldActions[static_cast<size_t>(signal)];
86     if (signal == Signal::Usr) {
87         if (oldAction.sa_sigaction)
88             oldAction.sa_sigaction(sig, info, mcontext);
89         return;
90     }
91
92     if (!didHandle) {
93         if (oldAction.sa_sigaction) {
94             oldAction.sa_sigaction(sig, info, mcontext);
95             return;
96         }
97
98         restoreDefault();
99         return;
100     }
101 }
102
103 void installSignalHandler(Signal signal, SignalHandler&& handler)
104 {
105     ASSERT(signal < Signal::Unknown);
106     std::call_once(initializeOnceFlags[static_cast<size_t>(signal)], [&] {
107         handlers[static_cast<size_t>(signal)].construct();
108
109         struct sigaction action;
110         action.sa_sigaction = jscSignalHandler;
111         auto result = sigfillset(&action.sa_mask);
112         RELEASE_ASSERT(!result);
113         action.sa_flags = SA_SIGINFO;
114         result = sigaction(toSystemSignal(signal), &action, &oldActions[static_cast<size_t>(signal)]);
115         RELEASE_ASSERT(!result);
116     });
117
118     handlers[static_cast<size_t>(signal)]->add(WTFMove(handler));
119 }
120
121 } // namespace WTF
122
123 #endif // USE(PTHREADS)