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);
205 passed &= expectResult(current, posix_kill(-1, 0), 0, 0);
208 passed &= expectResult(
209 current, posix_tgkill(context->deniedProcess->getId(), context->deniedTarget->getId(), 0), -1,
210 Error::NotEnoughPermissions);
213 context->passed += 1;
219struct SuspendContext {
220 explicit SuspendContext(
Process* process) : process(process), entered(0), returned(0) {}
227int suspendTarget(
void* parameter) {
228 SuspendContext* context =
reinterpret_cast<SuspendContext*
>(parameter);
229 context->entered += 1;
230 context->process->suspend();
231 context->returned += 1;
235bool waitForSuspension(
Process* process) {
236 for (
size_t attempt = 0; attempt < HostedAttempts; ++attempt) {
237 if (process->isSuspended()) {
246bool runHostedThreadSignalSyscallRegressions(
Process* kernelProcess) {
247 PosixProcess* caller = makeProcess(kernelProcess, 1000);
249 installDisposition(callerSubsystem, SIGUSR1, 0);
250 installDisposition(callerSubsystem, SIGUSR2, 2);
251 installDisposition(callerSubsystem, MuslTimerSignal, 0);
252 installDisposition(callerSubsystem, MuslCancelSignal, 0);
253 installDisposition(callerSubsystem, FirstRealtimeSignal, 0);
254 installDisposition(callerSubsystem, LastRealtimeSignal, 0);
255 Thread* sameTarget =
new Thread(caller, dormantThread,
nullptr,
nullptr,
false,
true,
true);
257 PosixProcess* target = makeProcess(kernelProcess, 1000);
259 installDisposition(targetSubsystem, SIGUSR1, 0);
260 installDisposition(targetSubsystem, SIGUSR2, 2);
261 installDisposition(targetSubsystem, MuslSyncCallSignal, 0);
262 installDisposition(targetSubsystem, FirstRealtimeSignal, 0);
263 installDisposition(targetSubsystem, LastRealtimeSignal, 0);
264 new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
265 new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
266 Thread* remoteTarget =
new Thread(target, dormantThread,
nullptr,
nullptr,
false,
true,
true);
268 PosixProcess* denied = makeProcess(kernelProcess, 2000);
270 installDisposition(deniedSubsystem, SIGUSR1, 0);
271 Thread* deniedTarget =
new Thread(denied, dormantThread,
nullptr,
nullptr,
false,
true,
true);
273 ThreadSignalContext context(target, sameTarget, remoteTarget, denied, deniedTarget);
275 new Thread(caller, runThreadSignalCalls, &context,
nullptr,
false,
true,
true);
276 callerThread->setName(
"hosted thread-signal syscall caller");
282 SuspendContext suspendContext(target);
284 new Thread(kernelProcess, suspendTarget, &suspendContext,
nullptr,
false,
true,
true);
285 suspender->setName(
"hosted thread-signal suspended-target fixture");
286 const bool suspenderStarted = suspender->
start();
287 const bool suspended = suspenderStarted && waitForSuspension(target);
288 const bool callerStarted = suspended && callerThread->
start();
291 if (suspenderStarted && !suspended) {
294 if (target->isSuspended()) {
298 if (target->isSuspended()) {
301 if (!callerStarted) {
304 if (!suspenderStarted) {
308 const bool passed = suspended && callerJoined && suspenderJoined && suspendContext.entered == 1 &&
309 suspendContext.returned == 1 && context.entered == 1 && context.passed == 1;
317 "HOSTED-SYSCALL-TEST: FAIL thread-signal-syscalls: "
318 "tkill/tgkill target, mask, suspension, error, or permission semantics regressed");
322 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.