8#include "pedigree/kernel/Atomic.h"
9#include "pedigree/kernel/Log.h"
10#include "pedigree/kernel/errors.h"
11#include "pedigree/kernel/process/Process.h"
12#include "pedigree/kernel/process/Scheduler.h"
13#include "pedigree/kernel/process/SignalEvent.h"
14#include "pedigree/kernel/process/Thread.h"
15#include "pedigree/kernel/processor/Processor.h"
20#include "modules/subsys/posix/PosixProcess.h"
21#include "modules/subsys/posix/PosixSubsystem.h"
22#include "modules/subsys/posix/signal-syscalls.h"
25constexpr size_t HostedAttempts = 10000;
26constexpr size_t MuslTimerSignal = 32;
27constexpr size_t MuslCancelSignal = 33;
28constexpr size_t MuslSyncCallSignal = 34;
29constexpr size_t FirstRealtimeSignal = 35;
30constexpr size_t LastRealtimeSignal = 64;
31constexpr size_t FirstUnsupportedSignal = 65;
33void threadSignalHandler(
size_t) {}
35void installDisposition(
PosixSubsystem* subsystem,
size_t signal,
int type) {
38 handler->
pEvent =
new SignalEvent(
reinterpret_cast<uintptr_t
>(&threadSignalHandler), signal);
45 process->setUserId(uid);
46 process->setEffectiveUserId(uid);
47 process->setSavedUserId(uid);
51int dormantThread(
void*) {
55struct ThreadSignalContext {
58 : targetProcess(targetProcess),
59 sameTarget(sameTarget),
60 remoteTarget(remoteTarget),
61 deniedProcess(deniedProcess),
62 deniedTarget(deniedTarget),
75bool expectResult(
Thread* current,
int result,
int expectedResult,
size_t expectedError) {
76 return result == expectedResult && current->
getErrno() == expectedError;
79int runThreadSignalCalls(
void* parameter) {
80 ThreadSignalContext* context =
reinterpret_cast<ThreadSignalContext*
>(parameter);
84 context->entered += 1;
87 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), 0), 0, 0);
88 passed &= !context->sameTarget->hasEvent(SIGUSR1);
91 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), SIGUSR2), 0, 0);
92 passed &= !context->sameTarget->hasEvent(SIGUSR2);
94 const uint64_t originalMask = context->sameTarget->getSignalMask();
95 context->sameTarget->setSignalMask(originalMask | (
static_cast<uint64_t
>(1) << (SIGUSR1 - 1)));
97 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), SIGUSR1), 0, 0);
98 passed &= context->sameTarget->hasEvent(SIGUSR1) && !current->
hasEvent(SIGUSR1);
99 context->sameTarget->cullSignalEvent(SIGUSR1);
100 context->sameTarget->setSignalMask(originalMask);
102 context->sameTarget->setSignalMask(originalMask |
103 (
static_cast<uint64_t
>(1) << (MuslTimerSignal - 1)));
105 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), MuslTimerSignal), 0, 0);
106 passed &= context->sameTarget->hasEvent(MuslTimerSignal);
107 context->sameTarget->cullSignalEvent(MuslTimerSignal);
108 context->sameTarget->setSignalMask(originalMask);
112 expectResult(current, posix_tkill(context->sameTarget->getId(), MuslCancelSignal), 0, 0);
113 passed &= context->sameTarget->hasEvent(MuslCancelSignal);
114 context->sameTarget->cullSignalEvent(MuslCancelSignal);
117 passed &= expectResult(current, posix_tkill(0, 0), -1, Error::InvalidArgument);
119 passed &= expectResult(current, posix_tkill(-1, 0), -1, Error::InvalidArgument);
122 expectResult(current, posix_tkill(context->remoteTarget->getId(), FirstUnsupportedSignal), -1,
123 Error::NoSuchProcess);
125 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), FirstUnsupportedSignal),
126 -1, Error::InvalidArgument);
130 expectResult(current, posix_tgkill(caller->
getId(), context->sameTarget->getId(), 0), 0, 0);
132 passed &= expectResult(current, posix_tgkill(0, context->sameTarget->getId(), 0), -1,
133 Error::InvalidArgument);
135 passed &= expectResult(current, posix_tgkill(caller->
getId(), 0, 0), -1, Error::InvalidArgument);
138 passed &= expectResult(
140 posix_tgkill(context->targetProcess->getId(), context->remoteTarget->getId(), SIGUSR1), 0, 0);
141 passed &= context->remoteTarget->hasEvent(SIGUSR1);
142 context->remoteTarget->cullSignalEvent(SIGUSR1);
145 passed &= expectResult(
147 posix_tgkill(context->targetProcess->getId(), context->remoteTarget->getId(), SIGUSR2), 0, 0);
148 passed &= !context->remoteTarget->hasEvent(SIGUSR2);
151 passed &= expectResult(current,
152 posix_tgkill(context->targetProcess->getId(),
153 context->remoteTarget->getId(), MuslSyncCallSignal),
155 passed &= context->remoteTarget->hasEvent(MuslSyncCallSignal);
156 context->remoteTarget->cullSignalEvent(MuslSyncCallSignal);
158 const size_t realtimeSignals[] = {FirstRealtimeSignal, LastRealtimeSignal};
159 for (
size_t signal : realtimeSignals) {
160 context->sameTarget->setSignalMask(originalMask | (
static_cast<uint64_t
>(1) << (signal - 1)));
162 passed &= expectResult(current, posix_tkill(context->sameTarget->getId(), signal), 0, 0);
163 passed &= context->sameTarget->hasEvent(signal) && !current->
hasEvent(signal);
164 context->sameTarget->cullSignalEvent(signal);
165 context->sameTarget->setSignalMask(originalMask);
168 passed &= expectResult(
170 posix_tgkill(context->targetProcess->getId(), context->remoteTarget->getId(), signal), 0,
172 passed &= context->remoteTarget->hasEvent(signal);
173 context->remoteTarget->cullSignalEvent(signal);
176 passed &= expectResult(
178 posix_tgkill(context->deniedProcess->getId(), context->deniedTarget->getId(), signal), -1,
179 Error::NotEnoughPermissions);
183 passed &= expectResult(
184 current, posix_tgkill(context->targetProcess->getId(), INT_MAX, FirstUnsupportedSignal), -1,
185 Error::NoSuchProcess);
187 passed &= expectResult(
188 current, posix_tgkill(INT_MAX, context->remoteTarget->getId(), FirstUnsupportedSignal), -1,
189 Error::NoSuchProcess);
191 passed &= expectResult(current,
192 posix_tgkill(context->targetProcess->getId(),
193 context->remoteTarget->getId(), FirstUnsupportedSignal),
194 -1, Error::InvalidArgument);
197 passed &= expectResult(current, posix_kill(caller->
getId(), MuslCancelSignal), -1,
198 Error::InvalidArgument);
200 passed &= expectResult(current, posix_kill(caller->
getId(), FirstUnsupportedSignal), -1,
201 Error::InvalidArgument);
204 passed &= expectResult(
205 current, posix_tgkill(context->deniedProcess->getId(), context->deniedTarget->getId(), 0), -1,
206 Error::NotEnoughPermissions);
209 context->passed += 1;
215struct SuspendContext {
216 explicit SuspendContext(
Process* process) : process(process), entered(0), returned(0) {}
223int suspendTarget(
void* parameter) {
224 SuspendContext* context =
reinterpret_cast<SuspendContext*
>(parameter);
225 context->entered += 1;
226 context->process->suspend();
227 context->returned += 1;
231bool waitForSuspension(
Process* process) {
232 for (
size_t attempt = 0; attempt < HostedAttempts; ++attempt) {
233 if (process->isSuspended()) {
242bool runHostedThreadSignalSyscallRegressions(
Process* kernelProcess) {
243 PosixProcess* caller = makeProcess(kernelProcess, 1000);
245 installDisposition(callerSubsystem, SIGUSR1, 0);
246 installDisposition(callerSubsystem, SIGUSR2, 2);
247 installDisposition(callerSubsystem, MuslTimerSignal, 0);
248 installDisposition(callerSubsystem, MuslCancelSignal, 0);
249 installDisposition(callerSubsystem, FirstRealtimeSignal, 0);
250 installDisposition(callerSubsystem, LastRealtimeSignal, 0);
251 Thread* sameTarget =
new Thread(caller, dormantThread,
nullptr,
nullptr,
false,
true,
true);
253 PosixProcess* target = makeProcess(kernelProcess, 1000);
255 installDisposition(targetSubsystem, SIGUSR1, 0);
256 installDisposition(targetSubsystem, SIGUSR2, 2);
257 installDisposition(targetSubsystem, MuslSyncCallSignal, 0);
258 installDisposition(targetSubsystem, FirstRealtimeSignal, 0);
259 installDisposition(targetSubsystem, LastRealtimeSignal, 0);
260 new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
261 new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
262 Thread* remoteTarget =
new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
264 PosixProcess* denied = makeProcess(kernelProcess, 2000);
266 installDisposition(deniedSubsystem, SIGUSR1, 0);
267 Thread* deniedTarget =
new Thread(denied, dormantThread,
nullptr,
nullptr,
false,
true,
true);
269 ThreadSignalContext context(target, sameTarget, remoteTarget, denied, deniedTarget);
271 new Thread(caller, runThreadSignalCalls, &context,
nullptr,
false,
true,
true);
272 callerThread->setName(
"hosted thread-signal syscall caller");
278 SuspendContext suspendContext(target);
280 new Thread(kernelProcess, suspendTarget, &suspendContext,
nullptr,
false,
true,
true);
281 suspender->setName(
"hosted thread-signal suspended-target fixture");
282 const bool suspenderStarted = suspender->
start();
283 const bool suspended = suspenderStarted && waitForSuspension(target);
284 const bool callerStarted = suspended && callerThread->
start();
287 if (suspenderStarted && !suspended) {
290 if (target->isSuspended()) {
294 if (target->isSuspended()) {
297 if (!callerStarted) {
300 if (!suspenderStarted) {
304 const bool passed = suspended && callerJoined && suspenderJoined && suspendContext.entered == 1 &&
305 suspendContext.returned == 1 && context.entered == 1 && context.passed == 1;
313 "HOSTED-SYSCALL-TEST: FAIL thread-signal-syscalls: "
314 "tkill/tgkill target, mask, suspension, error, or permission semantics regressed");
318 NOTICE(
"HOSTED-SYSCALL-TEST: PASS thread-signal-syscalls");
void setSignalHandler(size_t sig, SignalHandler *handler)
static ProcessorInformation & information()
static Scheduler & instance()
void setErrno(size_t err)
void setUnwindState(UnwindType ut)
@ TerminateThread
Exit only this thread during Process exit.
bool hasEvent(Event *pEvent)
Process * getParent() const
int type
Type - 0 = normal, 1 = SIG_DFL, 2 = SIG_IGN.
SignalEvent * pEvent
Event for the signal handler.