Rework signal handling code

This commit is contained in:
EnderIce2 2024-03-25 23:21:27 +02:00
parent 3b1bd58a36
commit 3d1ecc3db0
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
10 changed files with 1040 additions and 711 deletions

View File

@ -169,15 +169,15 @@ nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame)
return true;
}
proc->Signals->SendSignal(SIGSEGV,
{Tasking::KILL_CRASH});
proc->Signals.SendSignal(SIGSEGV,
{Tasking::KILL_CRASH});
break;
}
case CPU::x86::Debug:
case CPU::x86::Breakpoint:
{
proc->Signals->SendSignal(SIGTRAP,
{Tasking::KILL_CRASH});
proc->Signals.SendSignal(SIGTRAP,
{Tasking::KILL_CRASH});
break;
}
case CPU::x86::DivideByZero:
@ -186,21 +186,21 @@ nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame)
case CPU::x86::x87FloatingPoint:
case CPU::x86::SIMDFloatingPoint:
{
proc->Signals->SendSignal(SIGFPE,
{Tasking::KILL_CRASH});
proc->Signals.SendSignal(SIGFPE,
{Tasking::KILL_CRASH});
break;
}
case CPU::x86::InvalidOpcode:
case CPU::x86::GeneralProtectionFault:
{
proc->Signals->SendSignal(SIGILL,
{Tasking::KILL_CRASH});
proc->Signals.SendSignal(SIGILL,
{Tasking::KILL_CRASH});
break;
}
case CPU::x86::DeviceNotAvailable:
{
proc->Signals->SendSignal(SIGBUS,
{Tasking::KILL_CRASH});
proc->Signals.SendSignal(SIGBUS,
{Tasking::KILL_CRASH});
break;
}
case CPU::x86::NonMaskableInterrupt:

View File

@ -18,171 +18,121 @@
#ifndef __FENNIX_KERNEL_SIGNAL_H__
#define __FENNIX_KERNEL_SIGNAL_H__
#include <unordered_map>
#include <syscalls.hpp>
#include <lock.hpp>
#include <types.h>
#include <bitset>
#include <list>
#include <syscall/linux/signals.hpp>
enum Signals : int
{
SIG_NULL = 0,
/**
* Process abort signal.
*/
SIGABRT,
/**
* Alarm clock.
*/
SIGALRM,
/**
* Access to an undefined portion of a memory object.
*/
SIGBUS,
/**
* Child process terminated, stopped, or continued.
*/
SIGCHLD,
/**
* Continue executing, if stopped.
*/
SIGCONT,
/**
* Erroneous arithmetic operation.
*/
SIGFPE,
/**
* Hangup.
*/
SIGHUP,
/**
* Illegal instruction.
*/
SIGILL,
/**
* Terminal interrupt signal.
*/
SIGINT,
/**
* Kill (cannot be caught or ignored).
*/
SIGKILL,
/**
* Write on a pipe with no one to read it.
*/
SIGPIPE,
/**
* Terminal quit signal.
*/
SIGQUIT,
/**
* Invalid memory reference.
*/
SIGSEGV,
/**
* Stop executing (cannot be caught or ignored).
*/
SIGSTOP,
/**
* Termination signal.
*/
SIGTERM,
/**
* Terminal stop signal.
*/
SIGTSTP,
/**
* Background process attempting read.
*/
SIGTTIN,
/**
* Background process attempting write.
*/
SIGTTOU,
/**
* User-defined signal 1.
*/
SIGUSR1,
/**
* User-defined signal 2.
*/
SIGUSR2,
/**
* Pollable event.
*/
SIGPOLL,
/**
* Profiling timer expired.
*/
SIGPROF,
/**
* Bad system call.
*/
SIGSYS,
/**
* Trace/breakpoint trap.
*/
SIGTRAP,
/**
* High bandwidth data is available at a socket.
*/
SIGURG,
/**
* Virtual timer expired.
*/
SIGVTALRM,
/**
* CPU time limit exceeded.
*/
SIGXCPU,
/**
* File size limit exceeded.
*/
SIGXFSZ,
/* Process abort signal. */
SIGABRT = 1,
/* Alarm clock. */
SIGALRM = 2,
/* Access to an undefined portion of a memory object. */
SIGBUS = 3,
/* Child process terminated, stopped, or continued. */
SIGCHLD = 4,
/* Continue executing, if stopped. */
SIGCONT = 5,
/* Erroneous arithmetic operation. */
SIGFPE = 6,
/* Hangup. */
SIGHUP = 7,
/* Illegal instruction. */
SIGILL = 8,
/* Terminal interrupt signal. */
SIGINT = 9,
/* Kill (cannot be caught or ignored). */
SIGKILL = 10,
/* Write on a pipe with no one to read it. */
SIGPIPE = 11,
/* Terminal quit signal. */
SIGQUIT = 12,
/* Invalid memory reference. */
SIGSEGV = 13,
/* Stop executing (cannot be caught or ignored). */
SIGSTOP = 14,
/* Termination signal. */
SIGTERM = 15,
/* Terminal stop signal. */
SIGTSTP = 16,
/* Background process attempting read. */
SIGTTIN = 17,
/* Background process attempting write. */
SIGTTOU = 18,
/* User-defined signal 1. */
SIGUSR1 = 19,
/* User-defined signal 2. */
SIGUSR2 = 20,
/* Pollable event. */
SIGPOLL = 21,
/* Profiling timer expired. */
SIGPROF = 22,
/* Bad system call. */
SIGSYS = 23,
/* Trace/breakpoint trap. */
SIGTRAP = 24,
/* High bandwidth data is available at a socket. */
SIGURG = 25,
/* Virtual timer expired. */
SIGVTALRM = 26,
/* CPU time limit exceeded. */
SIGXCPU = 27,
/* File size limit exceeded. */
SIGXFSZ = 28,
/**
* Reserved
*
* These are just to match Linux's signal numbers.
*/
SIGRSV1,
SIGRSV2,
SIGCOMP1 = 29,
SIGCOMP2 = 30,
SIGCOMP3 = 31,
/**
* Maximum signal number.
*/
SIGNAL_MAX
/* Real-time signals. */
SIGRTMIN = 32,
SIGRT_1 = 33,
SIGRT_2 = 34,
SIGRT_3 = 35,
SIGRT_4 = 36,
SIGRT_5 = 37,
SIGRT_6 = 38,
SIGRT_7 = 39,
SIGRT_8 = 40,
SIGRT_9 = 41,
SIGRT_10 = 42,
SIGRT_11 = 43,
SIGRT_12 = 44,
SIGRT_13 = 45,
SIGRT_14 = 46,
SIGRT_15 = 47,
SIGRT_16 = 48,
SIGRT_17 = 49,
SIGRT_18 = 50,
SIGRT_19 = 51,
SIGRT_20 = 52,
SIGRT_21 = 53,
SIGRT_22 = 54,
SIGRT_23 = 55,
SIGRT_24 = 56,
SIGRT_25 = 57,
SIGRT_26 = 58,
SIGRT_27 = 59,
SIGRT_28 = 60,
SIGRT_29 = 61,
SIGRT_30 = 62,
SIGRT_31 = 63,
SIGRTMAX = 64,
/* Maximum signal number. */
SIGNAL_MAX = SIGRTMAX
};
enum SignalDisposition
enum SignalDispositions
{
/**
* Terminate the process.
@ -210,21 +160,28 @@ enum SignalDisposition
SIG_CONT
};
enum SignalAction
enum SignalActions
{
SIG_BLOCK,
SIG_UNBLOCK,
SIG_SETMASK
};
enum SignalActionDisposition : long
{
SAD_ERR = -1,
SAD_DFL = 0,
SAD_IGN = 1,
};
#define SA_NOCLDSTOP 1
#define SA_NOCLDWAIT 2
#define SA_SIGINFO 4
#define SA_RESTORER 0x04000000
#define SA_ONSTACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#define __SI_PAD_SIZE \
(128 - 2 * sizeof(int) - sizeof(long))
@ -323,41 +280,32 @@ typedef struct
} __si_fields;
} siginfo_t;
struct sigaction
struct SignalAction
{
union
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
} __sa_handler;
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
void (*Handler)(int);
void (*Action)(int, siginfo_t *, void *);
sigset_t Disposition;
} sa_handler;
std::bitset<64> Mask;
unsigned long Flags;
void (*Restorer)(void);
};
namespace Tasking
{
__no_sanitize("shift") inline __always_inline
sigset_t
ToFlag(sigset_t sig)
{
return 1 << (sig - 1);
}
inline __always_inline
sigset_t
ToSig(sigset_t flag)
{
return __builtin_ctzl(flag) + 1;
}
class Signal
{
private:
struct SignalInfo
{
int sig;
union sigval val;
int sig = SIG_NULL;
union sigval val
{
0
};
pid_t tid = -1;
};
struct StackInfo
@ -388,109 +336,97 @@ namespace Tasking
void *TrampAddr = nullptr;
size_t TrampSz = 0;
std::list<SignalInfo> SignalQueue;
std::atomic<sigset_t> SignalMask = 0;
sigaction SignalAction[SIGNAL_MAX]{};
SignalDisposition sigDisp[SIGNAL_MAX];
std::list<SignalInfo> Queue;
SignalAction sa[64 + 1]{};
// std::bitset<SIGNAL_MAX> GlobalMask;
// SignalDispositions Disposition[SIGNAL_MAX];
std::list<SignalInfo> Watchers;
std::unordered_map<Signals, SignalDispositions> Disposition = {
{SIGHUP, SIG_TERM},
{SIGINT, SIG_TERM},
{SIGQUIT, SIG_TERM},
{SIGILL, SIG_CORE},
{SIGTRAP, SIG_CORE},
{SIGABRT, SIG_CORE},
{SIGBUS, SIG_CORE},
{SIGFPE, SIG_CORE},
{SIGKILL, SIG_TERM},
{SIGUSR1, SIG_TERM},
{SIGSEGV, SIG_CORE},
{SIGUSR2, SIG_TERM},
{SIGPIPE, SIG_TERM},
{SIGALRM, SIG_TERM},
{SIGTERM, SIG_TERM},
{SIGCOMP1, SIG_IGN},
{SIGCHLD, SIG_IGN},
{SIGCONT, SIG_CONT},
{SIGSTOP, SIG_STOP},
{SIGTSTP, SIG_STOP},
{SIGTTIN, SIG_STOP},
{SIGTTOU, SIG_STOP},
{SIGURG, SIG_IGN},
{SIGXCPU, SIG_CORE},
{SIGXFSZ, SIG_CORE},
{SIGVTALRM, SIG_TERM},
{SIGPROF, SIG_TERM},
{SIGCOMP2, SIG_IGN},
{SIGPOLL, SIG_TERM},
{SIGCOMP3, SIG_IGN},
{SIGSYS, SIG_CORE},
{SIGRTMIN, SIG_IGN},
{SIGRT_1, SIG_IGN},
{SIGRT_2, SIG_IGN},
{SIGRT_3, SIG_IGN},
{SIGRT_4, SIG_IGN},
{SIGRT_5, SIG_IGN},
{SIGRT_6, SIG_IGN},
{SIGRT_7, SIG_IGN},
{SIGRT_8, SIG_IGN},
{SIGRT_9, SIG_IGN},
{SIGRT_10, SIG_IGN},
{SIGRT_11, SIG_IGN},
{SIGRT_12, SIG_IGN},
{SIGRT_13, SIG_IGN},
{SIGRT_14, SIG_IGN},
{SIGRT_15, SIG_IGN},
{SIGRT_16, SIG_IGN},
{SIGRT_17, SIG_IGN},
{SIGRT_18, SIG_IGN},
{SIGRT_19, SIG_IGN},
{SIGRT_20, SIG_IGN},
{SIGRT_21, SIG_IGN},
{SIGRT_22, SIG_IGN},
{SIGRT_23, SIG_IGN},
{SIGRT_24, SIG_IGN},
{SIGRT_25, SIG_IGN},
{SIGRT_26, SIG_IGN},
{SIGRT_27, SIG_IGN},
{SIGRT_28, SIG_IGN},
{SIGRT_29, SIG_IGN},
{SIGRT_30, SIG_IGN},
{SIGRT_31, SIG_IGN},
{SIGRTMAX, SIG_IGN}};
bool LinuxSig();
int ConvertToLinuxIfNecessary(int sig);
int ConvertToNativeIfNecessary(int sig);
sigset_t ConvertSigsetToLinuxIfNecessary(sigset_t sig);
sigset_t ConvertSigsetToNativeIfNecessary(sigset_t sig);
int MakeExitCode(int sig);
int MakeExitCode(Signals sig);
void InitTrampoline();
const sigset_t nMasks = ToFlag(SIGKILL) |
ToFlag(SIGSTOP) |
ToFlag(SIGCONT) |
ToFlag(SIGSEGV) |
ToFlag(SIGBUS) |
ToFlag(SIGILL) |
ToFlag(SIGFPE);
const sigset_t lMasks = ToFlag(linux_SIGKILL) |
ToFlag(linux_SIGSTOP) |
ToFlag(linux_SIGCONT) |
ToFlag(linux_SIGSEGV) |
ToFlag(linux_SIGBUS) |
ToFlag(linux_SIGILL) |
ToFlag(linux_SIGFPE);
void RemoveUnmaskable(sigset_t *sig)
{
if (LinuxSig())
*sig &= ~lMasks;
else
*sig &= ~nMasks;
}
bool CanHaveHandler(sigset_t sig)
{
switch (sig)
{
case SIGKILL:
case SIGSTOP:
case SIGCONT:
return false;
default:
return true;
}
}
SignalInfo GetAvailableSignal(void *thread);
public:
void *GetContext() { return ctx; }
Signals GetLastSignal() { return LastSignal; }
int AddWatcher(Signal *who, int sig);
int RemoveWatcher(Signal *who, int sig);
int AddWatcher(Signal *who, Signals sig);
int RemoveWatcher(Signal *who, Signals sig);
int AddSignal(int sig, union sigval val);
int RemoveSignal(int sig);
int AddSignal(Signals sig, union sigval val = {0}, pid_t tid = -1);
int RemoveSignal(Signals sig);
/**
* For scheduler use only
* @return True if there is a signal to handle
*/
bool HandleSignal(CPU::TrapFrame *tf);
void RestoreHandleSignal(SyscallsFrame *tf);
bool HandleSignal(CPU::TrapFrame *tf, void *thread);
void RestoreHandleSignal(SyscallsFrame *tf, void *thread);
/**
* Mask a signal
*
* @param sig The signal to set
*
* @return Old mask
*/
sigset_t Block(sigset_t sig);
/**
* Unmask a signal
*
* @param sig The signal to set
*
* @return Old mask
*/
sigset_t Unblock(sigset_t sig);
/**
* Set the signal mask
*
* @param sig The signal to set
*
* @return Old mask
*/
sigset_t SetMask(sigset_t sig);
sigset_t GetMask() { return SignalMask.load(); }
int SetAction(int sig, const sigaction act);
int GetAction(int sig, sigaction *act);
int SetAction(Signals sig, const SignalAction *act);
int GetAction(Signals sig, SignalAction *act);
/**
* Send a signal to the process
@ -498,39 +434,56 @@ namespace Tasking
* @param sig The signal to send
* (compatibility specific)
* @param val The value to send
* @param tid The thread ID to send the signal to
*
* @return 0 on success, -errno on error
*/
int SendSignal(int sig, union sigval val = {0});
int SendSignal(Signals sig, sigval val = {0}, pid_t tid = -1);
int WaitAnySignal();
bool HasPendingSignal();
bool HasPendingSignal() { return !Queue.empty(); }
/**
* Wait for a signal
*
* @param sig The signal to wait for
* (compatibility specific)
* @param val The value to wait for
*
* @return 0 on success, -errno on error
*/
int WaitSignal(int sig, union sigval *val);
int WaitSignal(Signals sig, union sigval *val);
/**
* Wait for a signal with a timeout
*
* @param sig The signal to wait for
* (compatibility specific)
* @param val The value to wait for
* @param timeout The timeout to wait for
*
* @return 0 on success, -errno on error
*/
int WaitSignalTimeout(int sig, union sigval *val, uint64_t timeout);
int WaitSignalTimeout(Signals sig, union sigval *val, uint64_t timeout);
Signal(void *ctx);
~Signal();
friend class ThreadSignal;
};
class ThreadSignal
{
private:
Signal &pSig;
public:
std::bitset<64> Mask = 0;
sigset_t Block(sigset_t sig);
sigset_t Unblock(sigset_t sig);
sigset_t SetMask(sigset_t sig);
sigset_t GetMask();
ThreadSignal(Signal &sig) : pSig(sig) {}
};
}

View File

@ -170,6 +170,8 @@
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
#define LINUX_REBOOT_CMD_KEXEC 0x45584543
#define SA_IMMUTABLE 0x00800000
typedef long __kernel_old_time_t;
typedef long __kernel_suseconds_t;
typedef int clockid_t;

View File

@ -20,6 +20,8 @@
#include <types.h>
#define linux_NSIG 64
#define linux_SIGHUP 1
#define linux_SIGINT 2
#define linux_SIGQUIT 3
@ -53,4 +55,14 @@
#define linux_SIGSYS 31
#define linux_SIGUNUSED linux_SIGSYS
#define linux_SIGRTMIN 32
#define linux_SIGRTMAX linux_NSIG
struct k_sigaction
{
void (*handler)(int);
unsigned long flags;
void (*restorer)(void);
unsigned mask[2];
};
#endif // !__FENNIX_KERNEL_LINUX_SIGNALS_H__

View File

@ -333,6 +333,9 @@ namespace Tasking
Memory::VirtualMemoryArea *vma;
Memory::StackGuard *Stack;
/* Signal */
ThreadSignal Signals;
/* CPU state */
#if defined(a64)
CPU::x64::TrapFrame Registers{};
@ -361,6 +364,7 @@ namespace Tasking
{
int *set_child_tid{};
int *clear_child_tid{};
pid_t tgid = 0;
} Linux{};
int SendSignal(int sig);
@ -437,6 +441,8 @@ namespace Tasking
uint16_t UserID = UINT16_MAX;
uint16_t GroupID = UINT16_MAX;
} Real, Effective;
pid_t ProcessGroupID = 0;
pid_t SessionID = 0;
} Security{};
TaskInfo Info{};
ThreadLocalStorage TLS{};
@ -457,7 +463,7 @@ namespace Tasking
Memory::ProgramBreak *ProgramBreak;
/* Other */
Signal *Signals;
Signal Signals;
/* Threads & Children */
std::list<TCB *> Threads;

View File

@ -39,13 +39,288 @@
using Tasking::PCB;
using Tasking::TCB;
static_assert(linux_SIGRTMIN == SIGRTMIN);
static_assert(linux_SIGRTMAX == SIGRTMAX);
struct SyscallData
{
const char *Name;
void *Handler;
};
void linux_fork_return(void *tableAddr)
#ifdef DEBUG
const char *lSigStr[] = {
"INVALID",
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGBUS",
"SIGFPE",
"SIGKILL",
"SIGUSR1",
"SIGSEGV",
"SIGUSR2",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"SIGSTKFLT",
"SIGCHLD",
"SIGCONT",
"SIGSTOP",
"SIGTSTP",
"SIGTTIN",
"SIGTTOU",
"SIGURG",
"SIGXCPU",
"SIGXFSZ",
"SIGVTALRM",
"SIGPROF",
"SIGWINCH",
"SIGPOLL",
"SIGPWR",
"SIGSYS",
"SIGRTMIN",
"SIGRT_1",
"SIGRT_2",
"SIGRT_3",
"SIGRT_4",
"SIGRT_5",
"SIGRT_6",
"SIGRT_7",
"SIGRT_8",
"SIGRT_9",
"SIGRT_10",
"SIGRT_11",
"SIGRT_12",
"SIGRT_13",
"SIGRT_14",
"SIGRT_15",
"SIGRT_16",
"SIGRT_17",
"SIGRT_18",
"SIGRT_19",
"SIGRT_20",
"SIGRT_21",
"SIGRT_22",
"SIGRT_23",
"SIGRT_24",
"SIGRT_25",
"SIGRT_26",
"SIGRT_27",
"SIGRT_28",
"SIGRT_29",
"SIGRT_30",
"SIGRT_31",
"SIGRTMAX",
};
#endif
const char *rlimitStr[] = {
"RLIMIT_CPU",
"RLIMIT_FSIZE",
"RLIMIT_DATA",
"RLIMIT_STACK",
"RLIMIT_CORE",
"RLIMIT_RSS",
"RLIMIT_NPROC",
"RLIMIT_NOFILE",
"RLIMIT_MEMLOCK",
"RLIMIT_AS",
"RLIMIT_LOCKS",
"RLIMIT_SIGPENDING",
"RLIMIT_MSGQUEUE",
"RLIMIT_NICE",
"RLIMIT_RTPRIO",
"RLIMIT_RTTIME",
"RLIMIT_NLIMITS",
};
static const struct
{
int linuxSignal;
Signals nativeSignal;
SignalDispositions nativeDisposition;
} signalMapping[] = {
{linux_SIGHUP, SIGHUP, SIG_TERM},
{linux_SIGINT, SIGINT, SIG_TERM},
{linux_SIGQUIT, SIGQUIT, SIG_TERM},
{linux_SIGILL, SIGILL, SIG_CORE},
{linux_SIGTRAP, SIGTRAP, SIG_CORE},
{linux_SIGABRT, SIGABRT, SIG_CORE},
{linux_SIGBUS, SIGBUS, SIG_CORE},
{linux_SIGFPE, SIGFPE, SIG_CORE},
{linux_SIGKILL, SIGKILL, SIG_TERM},
{linux_SIGUSR1, SIGUSR1, SIG_TERM},
{linux_SIGSEGV, SIGSEGV, SIG_CORE},
{linux_SIGUSR2, SIGUSR2, SIG_TERM},
{linux_SIGPIPE, SIGPIPE, SIG_TERM},
{linux_SIGALRM, SIGALRM, SIG_TERM},
{linux_SIGTERM, SIGTERM, SIG_TERM},
{linux_SIGSTKFLT, SIGCOMP1, SIG_IGN},
{linux_SIGCHLD, SIGCHLD, SIG_IGN},
{linux_SIGCONT, SIGCONT, SIG_CONT},
{linux_SIGSTOP, SIGSTOP, SIG_STOP},
{linux_SIGTSTP, SIGTSTP, SIG_STOP},
{linux_SIGTTIN, SIGTTIN, SIG_STOP},
{linux_SIGTTOU, SIGTTOU, SIG_STOP},
{linux_SIGURG, SIGURG, SIG_IGN},
{linux_SIGXCPU, SIGXCPU, SIG_CORE},
{linux_SIGXFSZ, SIGXFSZ, SIG_CORE},
{linux_SIGVTALRM, SIGVTALRM, SIG_TERM},
{linux_SIGPROF, SIGPROF, SIG_TERM},
{linux_SIGWINCH, SIGCOMP2, SIG_IGN},
{linux_SIGPOLL, SIGPOLL, SIG_TERM},
{linux_SIGPWR, SIGCOMP3, SIG_IGN},
{linux_SIGSYS, SIGSYS, SIG_CORE},
{linux_SIGRTMIN, SIGRTMIN, SIG_IGN},
{linux_SIGRTMIN + 1, SIGRT_1, SIG_IGN},
{linux_SIGRTMIN + 2, SIGRT_2, SIG_IGN},
{linux_SIGRTMIN + 3, SIGRT_3, SIG_IGN},
{linux_SIGRTMIN + 4, SIGRT_4, SIG_IGN},
{linux_SIGRTMIN + 5, SIGRT_5, SIG_IGN},
{linux_SIGRTMIN + 6, SIGRT_6, SIG_IGN},
{linux_SIGRTMIN + 7, SIGRT_7, SIG_IGN},
{linux_SIGRTMIN + 8, SIGRT_8, SIG_IGN},
{linux_SIGRTMIN + 9, SIGRT_9, SIG_IGN},
{linux_SIGRTMIN + 10, SIGRT_10, SIG_IGN},
{linux_SIGRTMIN + 11, SIGRT_11, SIG_IGN},
{linux_SIGRTMIN + 12, SIGRT_12, SIG_IGN},
{linux_SIGRTMIN + 13, SIGRT_13, SIG_IGN},
{linux_SIGRTMIN + 14, SIGRT_14, SIG_IGN},
{linux_SIGRTMIN + 15, SIGRT_15, SIG_IGN},
{linux_SIGRTMIN + 16, SIGRT_16, SIG_IGN},
{linux_SIGRTMIN + 17, SIGRT_17, SIG_IGN},
{linux_SIGRTMIN + 18, SIGRT_18, SIG_IGN},
{linux_SIGRTMIN + 19, SIGRT_19, SIG_IGN},
{linux_SIGRTMIN + 20, SIGRT_20, SIG_IGN},
{linux_SIGRTMIN + 21, SIGRT_21, SIG_IGN},
{linux_SIGRTMIN + 22, SIGRT_22, SIG_IGN},
{linux_SIGRTMIN + 23, SIGRT_23, SIG_IGN},
{linux_SIGRTMIN + 24, SIGRT_24, SIG_IGN},
{linux_SIGRTMIN + 25, SIGRT_25, SIG_IGN},
{linux_SIGRTMIN + 26, SIGRT_26, SIG_IGN},
{linux_SIGRTMIN + 27, SIGRT_27, SIG_IGN},
{linux_SIGRTMIN + 28, SIGRT_28, SIG_IGN},
{linux_SIGRTMIN + 29, SIGRT_29, SIG_IGN},
{linux_SIGRTMIN + 30, SIGRT_30, SIG_IGN},
{linux_SIGRTMIN + 31, SIGRT_31, SIG_IGN},
{linux_SIGRTMAX, SIGRTMAX, SIG_IGN}};
int ConvertSignalToLinux(Signals sig)
{
if (sig >= SIGRTMIN && sig <= SIGRTMAX)
return sig; /* We ignore for now */
foreach (auto &mapping in signalMapping)
{
if (mapping.nativeSignal == sig)
{
// debug("Converted \"%s\"(%d) to \"%s\"(%d)",
// sigStr[mapping.nativeSignal], sig,
// lSigStr[mapping.linuxSignal], mapping.linuxSignal);
return mapping.linuxSignal;
}
}
debug("Unknown signal %d", sig);
// assert(!"Unknown signal");
return SIG_NULL;
}
Signals ConvertSignalToNative(int sig)
{
if (sig >= linux_SIGRTMIN && sig <= linux_SIGRTMAX)
return (Signals)sig; /* We ignore for now */
foreach (auto &mapping in signalMapping)
{
if (mapping.linuxSignal == sig)
{
// debug("Converted \"%s\"(%d) to \"%s\"(%d)",
// lSigStr[mapping.linuxSignal], sig,
// sigStr[mapping.nativeSignal], mapping.nativeSignal);
return mapping.nativeSignal;
}
}
debug("Unknown signal %d", sig);
// assert(!"Unknown signal");
return SIG_NULL;
}
unsigned long ConvertMaskToNative(unsigned long mask)
{
unsigned long ret = 0;
for (int i = 0; i < 64; i++)
{
if (mask & (1ul << i))
{
int sig = ConvertSignalToNative(i + 1);
if (unlikely(sig == SIG_NULL))
continue;
ret |= 1ul << (sig - 1);
}
}
return ret;
// std::bitset<SIGNAL_MAX + 1> bitMask(mask);
// for (int i = 0; i < SIGNAL_MAX + 1; i++)
// {
// if (bitMask.test(i))
// ret |= 1 << (ConvertSignalToNative(i + 1) - 1);
// }
}
unsigned long ConvertMaskToLinux(unsigned long mask)
{
unsigned long ret = 0;
for (int i = 0; i < 64; i++)
{
if (mask & (1ul << i))
{
int sig = ConvertSignalToLinux((Signals)(i + 1));
if (unlikely(sig == SIG_NULL))
continue;
ret |= 1ul << (sig - 1);
}
}
return ret;
// std::bitset<linux_SIGUNUSED + 1> bitMask(mask);
// for (int i = 0; i < linux_SIGUNUSED + 1; i++)
// {
// if (bitMask.test(i))
// ret |= 1 << (ConvertSignalToLinux(i + 1) - 1);
// }
}
void SetSigActToNative(const k_sigaction *linux, SignalAction *native)
{
native->sa_handler.Handler = linux->handler;
native->Flags = linux->flags;
native->Restorer = linux->restorer;
unsigned long mask = ((unsigned long)linux->mask[1] << 32) | linux->mask[0];
native->Mask = std::bitset<64>(ConvertMaskToNative(mask));
debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask);
}
void SetSigActToLinux(const SignalAction *native, k_sigaction *linux)
{
linux->handler = native->sa_handler.Handler;
linux->flags = native->Flags;
linux->restorer = native->Restorer;
unsigned long mask = native->Mask.to_ulong();
mask = ConvertMaskToLinux(mask);
linux->mask[0] = mask & 0xFFFFFFFF;
linux->mask[1] = (mask >> 32) & 0xFFFFFFFF;
debug("m0:%#lx m1:%#lx | n:%#lx", linux->mask[0], linux->mask[1], native->Mask);
}
void __LinuxForkReturn(void *tableAddr)
{
#if defined(a64)
asmv("movq %0, %%cr3" ::"r"(tableAddr)); /* Load process page table */
@ -56,7 +331,7 @@ void linux_fork_return(void *tableAddr)
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
#elif defined(a32)
#warning "linux_fork_return not implemented for i386"
#warning "__LinuxForkReturn not implemented for i386"
#endif
__builtin_unreachable();
}
@ -648,7 +923,7 @@ static int linux_dup2(SysFrm *, int oldfd, int newfd)
static int linux_pause(SysFrm *)
{
PCB *pcb = thisProcess;
return pcb->Signals->WaitAnySignal();
return pcb->Signals.WaitAnySignal();
}
/* https://man7.org/linux/man-pages/man2/nanosleep.2.html */
@ -690,7 +965,7 @@ static int linux_nanosleep(SysFrm *,
while (time < sleepTime)
{
if (pcb->Signals->HasPendingSignal())
if (pcb->Signals.HasPendingSignal())
{
debug("sleep interrupted by signal");
return -EINTR;
@ -739,6 +1014,9 @@ static pid_t linux_fork(SysFrm *sf)
return -EAGAIN;
}
NewProcess->Security.ProcessGroupID = Parent->Security.ProcessGroupID;
NewProcess->Security.SessionID = Parent->Security.SessionID;
NewProcess->PageTable = Parent->PageTable->Fork();
NewProcess->vma->Table = NewProcess->PageTable;
NewProcess->vma->Fork(Parent->vma);
@ -773,7 +1051,7 @@ static pid_t linux_fork(SysFrm *sf)
NewThread->Security.IsCritical = Thread->Security.IsCritical;
NewThread->Registers = Thread->Registers;
#if defined(a64)
NewThread->Registers.rip = (uintptr_t)linux_fork_return;
NewThread->Registers.rip = (uintptr_t)__LinuxForkReturn;
/* For sysretq */
NewThread->Registers.rdi = (uintptr_t)NewProcess->PageTable;
NewThread->Registers.rcx = sf->ReturnAddress;
@ -789,7 +1067,7 @@ static pid_t linux_fork(SysFrm *sf)
#endif
debug("ret addr: %#lx, stack: %#lx ip: %#lx", sf->ReturnAddress,
sf->StackPointer, (uintptr_t)linux_fork_return);
sf->StackPointer, (uintptr_t)__LinuxForkReturn);
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)",
Thread->Name, Thread->ID,
NewThread->Name, NewThread->ID);
@ -1077,7 +1355,9 @@ static pid_t linux_wait4(SysFrm *, pid_t pid, int *wstatus,
int ExitStatus = child->ExitCode.load();
bool ProcessSignaled = true;
bool CoreDumped = true;
int TermSignal = child->Signals->GetLastSignal();
int TermSignal = child->Signals.GetLastSignal();
TermSignal = ConvertSignalToLinux((Signals)TermSignal);
assert(TermSignal != SIG_NULL);
debug("Process returned %d", ExitStatus);
@ -1234,8 +1514,8 @@ static pid_t linux_wait4(SysFrm *, pid_t pid, int *wstatus,
/* https://man7.org/linux/man-pages/man2/kill.2.html */
static int linux_kill(SysFrm *, pid_t pid, int sig)
{
PCB *target = thisProcess->GetContext()->GetProcessByID(pid);
if (!target)
PCB *pcb = thisProcess->GetContext()->GetProcessByID(pid);
if (!pcb)
return -ESRCH;
/* TODO: Check permissions */
@ -1245,8 +1525,21 @@ static int linux_kill(SysFrm *, pid_t pid, int sig)
if (pid == 0)
{
fixme("Sending signal %d to all processes", sig);
return -ENOSYS;
bool found = false;
Signals nSig = ConvertSignalToNative(sig);
assert(nSig != SIG_NULL);
foreach (auto proc in pcb->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID == thisProcess->Security.ProcessGroupID)
{
debug("Sending signal %s to %s(%d)", lSigStr[sig], proc->Name, proc->ID);
proc->SendSignal(nSig);
found = true;
}
}
if (!found)
return -ESRCH;
return 0;
}
if (pid == -1)
@ -1261,7 +1554,9 @@ static int linux_kill(SysFrm *, pid_t pid, int sig)
return -ENOSYS;
}
return target->Signals->SendSignal(sig);
Signals nSig = ConvertSignalToNative(sig);
assert(nSig != SIG_NULL);
return pcb->SendSignal(nSig);
}
/* https://man7.org/linux/man-pages/man2/uname.2.html */
@ -1510,17 +1805,13 @@ static pid_t linux_getpgid(SysFrm *, pid_t pid)
{
PCB *pcb = thisProcess;
if (pid == 0)
{
fixme("pid=0 is stub!");
return 0;
}
return pcb->Security.ProcessGroupID;
PCB *target = pcb->GetContext()->GetProcessByID(pid);
if (!target)
return -ESRCH;
stub;
return 0;
return target->Security.ProcessGroupID;
}
/* https://man7.org/linux/man-pages/man2/setpgid.2.html */
@ -1529,7 +1820,7 @@ static int linux_setpgid(SysFrm *, pid_t pid, pid_t pgid)
PCB *pcb = thisProcess;
if (pid == 0)
{
fixme("pid=0 is stub!");
pcb->Security.ProcessGroupID = pgid;
return 0;
}
@ -1537,10 +1828,13 @@ static int linux_setpgid(SysFrm *, pid_t pid, pid_t pgid)
if (!target)
return -ESRCH;
if (pgid < 0)
return -EINVAL;
if (pgid == 0)
{
target->Security.ProcessGroupID = target->ID;
return 0;
}
fixme("setpgid(%d, %d) is stub!", pid, pgid);
target->Security.ProcessGroupID = pgid;
return 0;
}
@ -1702,16 +1996,22 @@ static int linux_reboot(SysFrm *, int magic, int magic2, int cmd, void *arg)
}
/* https://man7.org/linux/man-pages/man2/sigaction.2.html */
static int linux_sigaction(SysFrm *, int signum,
const struct sigaction *act,
struct sigaction *oldact)
static int linux_sigaction(SysFrm *, int signum, const k_sigaction *act,
k_sigaction *oldact, size_t sigsetsize)
{
if (signum == linux_SIGKILL || signum == linux_SIGSTOP)
if (signum < 1 || signum > linux_SIGRTMAX ||
signum == linux_SIGKILL || signum == linux_SIGSTOP)
{
debug("Invalid signal %d", signum);
return -EINVAL;
}
if (sigsetsize != sizeof(sigset_t))
{
warn("Unsupported sigsetsize %d!", sigsetsize);
return -EINVAL;
}
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
@ -1727,13 +2027,35 @@ static int linux_sigaction(SysFrm *, int signum,
int ret = 0;
if (pOldact)
ret = pcb->Signals->GetAction(signum, pOldact);
{
Signals nSig = ConvertSignalToNative(signum);
assert(nSig != SIG_NULL);
SignalAction nSA{};
SetSigActToNative(pOldact, &nSA);
ret = pcb->Signals.GetAction(nSig, &nSA);
SetSigActToLinux(&nSA, pOldact);
}
if (unlikely(ret < 0))
return ret;
if (pAct)
ret = pcb->Signals->SetAction(signum, *pAct);
{
if (pAct->flags & SA_IMMUTABLE)
{
warn("Immutable signal %d", signum);
return -EINVAL;
}
Signals nSig = ConvertSignalToNative(signum);
assert(nSig != SIG_NULL);
SignalAction nSA{};
SetSigActToNative(pAct, &nSA);
ret = pcb->Signals.SetAction(nSig, &nSA);
SetSigActToLinux(&nSA, (k_sigaction *)pAct);
}
return ret;
}
@ -1750,7 +2072,8 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set,
return -EINVAL;
}
PCB *pcb = thisProcess;
TCB *tcb = thisThread;
PCB *pcb = tcb->Parent;
Memory::VirtualMemoryArea *vma = pcb->vma;
if (vma->UserCheck(set) < 0 && set != nullptr)
@ -1765,21 +2088,25 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set,
how, pSet ? *pSet : 0, pOldset ? *pOldset : 0);
if (pOldset)
*pOldset = pcb->Signals->GetMask();
{
*pOldset = tcb->Signals.GetMask();
*pOldset = ConvertMaskToLinux(*pOldset);
}
if (!pSet)
return 0;
sigset_t nativeSet = ConvertMaskToNative(*pSet);
switch (how)
{
case SIG_BLOCK:
pcb->Signals->Block(*pSet);
tcb->Signals.Block(nativeSet);
break;
case SIG_UNBLOCK:
pcb->Signals->Unblock(*pSet);
tcb->Signals.Unblock(nativeSet);
break;
case SIG_SETMASK:
pcb->Signals->SetMask(*pSet);
tcb->Signals.SetMask(nativeSet);
break;
default:
warn("Invalid how %#x", how);
@ -1791,7 +2118,7 @@ static int linux_sigprocmask(SysFrm *, int how, const sigset_t *set,
/* https://man7.org/linux/man-pages/man2/sigreturn.2.html */
static void linux_sigreturn(SysFrm *sf)
{
thisProcess->Signals->RestoreHandleSignal(sf);
thisProcess->Signals.RestoreHandleSignal(sf, thisThread);
}
/* https://man7.org/linux/man-pages/man2/gettid.2.html */
@ -1803,14 +2130,13 @@ static pid_t linux_gettid(SysFrm *)
/* https://man7.org/linux/man-pages/man2/tkill.2.html */
static int linux_tkill(SysFrm *, int tid, int sig)
{
Tasking::PCB *pcb = thisProcess;
Tasking::TCB *tcb = pcb->GetThread(tid);
Tasking::TCB *tcb = thisProcess->GetThread(tid);
if (!tcb)
return -ESRCH;
Signals nSig = ConvertSignalToNative(sig);
assert(nSig != SIG_NULL);
return pcb->Signals.SendSignal(nSig);
return tcb->SendSignal(nSig);
}
/* https://man7.org/linux/man-pages/man2/set_tid_address.2.html */
@ -1919,6 +2245,7 @@ static int linux_clock_gettime(SysFrm *, clockid_t clockid, struct timespec *tp)
return 0;
}
/* https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html */
static int linux_clock_nanosleep(SysFrm *, clockid_t clockid, int flags,
const struct timespec *request,
struct timespec *remain)
@ -1981,12 +2308,29 @@ static __noreturn void linux_exit_group(SysFrm *sf, int status)
/* https://man7.org/linux/man-pages/man2/tgkill.2.html */
static int linux_tgkill(SysFrm *sf, pid_t tgid, pid_t tid, int sig)
{
Tasking::TCB *target = thisProcess->GetContext()->GetThreadByID(tid, thisProcess);
if (!target)
return -ESRCH;
Tasking::TCB *tcb = thisProcess->GetThread(tid);
if (!tcb || tcb->Linux.tgid != tgid)
{
debug("Invalid tgid %d tid %d", tgid, tid);
fixme("semi-stub: %d %d %d", tgid, tid, sig);
return target->Parent->Signals->SendSignal(sig);
tcb = nullptr;
foreach (auto t in thisProcess->Threads)
{
if (t->Linux.tgid == tgid)
{
debug("Found tgid %d tid %d", tgid, t->ID);
tcb = t;
break;
}
}
if (!tcb)
return -ESRCH;
}
Signals nSig = ConvertSignalToNative(sig);
assert(nSig != SIG_NULL);
return tcb->SendSignal(nSig);
}
/* https://man7.org/linux/man-pages/man2/open.2.html */
@ -2098,36 +2442,20 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource,
UNUSED(pNewLimit);
if (new_limit)
debug("new limit: rlim_cur:%ld rlim_max:%ld", pNewLimit->rlim_cur, pNewLimit->rlim_max);
debug("new limit: rlim_cur:%#lx rlim_max:%#lx", pNewLimit->rlim_cur, pNewLimit->rlim_max);
if (old_limit)
debug("old limit: rlim_cur:%ld rlim_max:%ld", pOldLimit->rlim_cur, pOldLimit->rlim_max);
debug("old limit: rlim_cur:%#lx rlim_max:%#lx", pOldLimit->rlim_cur, pOldLimit->rlim_max);
switch (resource)
{
case RLIMIT_NOFILE:
{
fixme("Setting RLIMIT_NOFILE is stub");
return 0;
}
case RLIMIT_STACK:
{
fixme("Setting RLIMIT_STACK is stub");
return 0;
}
case RLIMIT_NPROC:
{
fixme("Setting RLIMIT_NPROC is stub");
return 0;
}
case RLIMIT_FSIZE:
{
fixme("Setting RLIMIT_FSIZE is stub");
return 0;
}
case RLIMIT_CPU:
case RLIMIT_FSIZE:
case RLIMIT_DATA:
case RLIMIT_STACK:
case RLIMIT_CORE:
case RLIMIT_RSS:
case RLIMIT_NPROC:
case RLIMIT_NOFILE:
case RLIMIT_MEMLOCK:
case RLIMIT_AS:
case RLIMIT_LOCKS:
@ -2138,8 +2466,8 @@ static int linux_prlimit64(SysFrm *, pid_t pid, int resource,
case RLIMIT_RTTIME:
case RLIMIT_NLIMITS:
{
fixme("resource %d is stub", resource);
return -ENOSYS;
fixme("resource %s(%d) is stub", rlimitStr[resource], resource);
return 0; /* just return 0 */
}
default:
{

View File

@ -18,6 +18,7 @@
#include <task.hpp>
#include <dumper.hpp>
#include <signal.hpp>
#include <convert.h>
#include <lock.hpp>
#include <printf.h>
@ -58,7 +59,7 @@ namespace Tasking
int PCB::SendSignal(int sig)
{
return this->Signals->SendSignal(sig);
return this->Signals.SendSignal((enum Signals)sig);
}
void PCB::SetState(TaskState state)
@ -138,7 +139,8 @@ namespace Tasking
TaskExecutionMode ExecutionMode,
bool UseKernelPageTable,
uint16_t UserID, uint16_t GroupID)
: Node(ProcFS, std::to_string(ctx->NextPID), NodeType::DIRECTORY)
: Node(ProcFS, std::to_string(ctx->NextPID), NodeType::DIRECTORY),
Signals(this)
{
debug("+ %#lx", this);
@ -214,7 +216,6 @@ namespace Tasking
this->vma = new Memory::VirtualMemoryArea(this->PageTable);
this->ProgramBreak = new Memory::ProgramBreak(this->PageTable, this->vma);
this->Signals = new Signal(this);
debug("Process page table: %#lx", this->PageTable);
debug("Created %s process \"%s\"(%d). Parent \"%s\"(%d)",
@ -230,7 +231,6 @@ namespace Tasking
this->AllocatedMemory += sizeof(Memory::VirtualMemoryArea);
this->AllocatedMemory += sizeof(Memory::ProgramBreak);
this->AllocatedMemory += sizeof(SymbolResolver::Symbols);
this->AllocatedMemory += sizeof(Signal);
this->Info.SpawnTime = TimeManager->GetCounter();
@ -250,9 +250,6 @@ namespace Tasking
don't get scheduled anymore */
ctx->PopProcess(this);
debug("Freeing signals");
delete this->Signals;
debug("Freeing allocated memory");
delete this->ProgramBreak;
delete this->vma;

View File

@ -678,7 +678,7 @@ namespace Tasking::Scheduler
CPU::x32::wrmsr(CPU::x32::MSR_FS_BASE, CurrentCPU->CurrentThread->FSBase);
#endif
CurrentCPU->CurrentProcess->Signals->HandleSignal(Frame);
CurrentCPU->CurrentProcess->Signals.HandleSignal(Frame, CurrentCPU->CurrentThread.load());
if (!ProcessNotChanged)
(&CurrentCPU->CurrentProcess->Info)->LastUpdateTime = TimeManager->GetCounter();

View File

@ -30,73 +30,72 @@
#include "../kernel.h"
#ifdef DEBUG
const char *lSigStr[] = {
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGBUS",
"SIGFPE",
"SIGKILL",
"SIGUSR1",
"SIGSEGV",
"SIGUSR2",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"SIGSTKFLT",
"SIGCHLD",
"SIGCONT",
"SIGSTOP",
"SIGTSTP",
"SIGTTIN",
"SIGTTOU",
"SIGURG",
"SIGXCPU",
"SIGXFSZ",
"SIGVTALRM",
"SIGPROF",
"SIGWINCH",
"SIGPOLL",
"SIGPWR",
"SIGSYS",
"SIGUNUSED",
};
const char *sigStr[] = {
"INVALID ",
"SIGABRT ",
"SIGALRM ",
"SIGBUS ",
"SIGCHLD ",
"SIGCONT ",
"SIGFPE ",
"SIGHUP ",
"SIGILL ",
"SIGINT ",
"SIGKILL ",
"SIGPIPE ",
"SIGQUIT ",
"SIGSEGV ",
"SIGSTOP ",
"SIGTERM ",
"SIGTSTP ",
"SIGTTIN ",
"SIGTTOU ",
"SIGUSR1 ",
"SIGUSR2 ",
"SIGPOLL ",
"SIGPROF ",
"SIGSYS ",
"SIGTRAP ",
"SIGURG ",
"SIGVTALRM",
"SIGXCPU ",
"SIGXFSZ ",
"SIGRSV1 ",
"SIGRSV2 ",
/* 0 */ "INVALID",
/* 1 */ "SIGABRT",
/* 2 */ "SIGALRM",
/* 3 */ "SIGBUS",
/* 4 */ "SIGCHLD",
/* 5 */ "SIGCONT",
/* 6 */ "SIGFPE",
/* 7 */ "SIGHUP",
/* 8 */ "SIGILL",
/* 9 */ "SIGINT",
/* 10 */ "SIGKILL",
/* 11 */ "SIGPIPE",
/* 12 */ "SIGQUIT",
/* 13 */ "SIGSEGV",
/* 14 */ "SIGSTOP",
/* 15 */ "SIGTERM",
/* 16 */ "SIGTSTP",
/* 17 */ "SIGTTIN",
/* 18 */ "SIGTTOU",
/* 19 */ "SIGUSR1",
/* 20 */ "SIGUSR2",
/* 21 */ "SIGPOLL",
/* 22 */ "SIGPROF",
/* 23 */ "SIGSYS",
/* 24 */ "SIGTRAP",
/* 25 */ "SIGURG",
/* 26 */ "SIGVTALRM",
/* 27 */ "SIGXCPU",
/* 28 */ "SIGXFSZ",
/* 29 */ "SIGCOMP1",
/* 30 */ "SIGCOMP2",
/* 31 */ "SIGCOMP3",
/* 32 */ "SIGRTMIN",
/* 33 */ "SIGRT_1",
/* 34 */ "SIGRT_2",
/* 35 */ "SIGRT_3",
/* 36 */ "SIGRT_4",
/* 37 */ "SIGRT_5",
/* 38 */ "SIGRT_6",
/* 39 */ "SIGRT_7",
/* 40 */ "SIGRT_8",
/* 41 */ "SIGRT_9",
/* 42 */ "SIGRT_10",
/* 43 */ "SIGRT_11",
/* 44 */ "SIGRT_12",
/* 45 */ "SIGRT_13",
/* 46 */ "SIGRT_14",
/* 47 */ "SIGRT_15",
/* 48 */ "SIGRT_16",
/* 49 */ "SIGRT_17",
/* 50 */ "SIGRT_18",
/* 51 */ "SIGRT_19",
/* 52 */ "SIGRT_20",
/* 53 */ "SIGRT_21",
/* 54 */ "SIGRT_22",
/* 55 */ "SIGRT_23",
/* 56 */ "SIGRT_24",
/* 57 */ "SIGRT_25",
/* 58 */ "SIGRT_26",
/* 59 */ "SIGRT_27",
/* 60 */ "SIGRT_28",
/* 61 */ "SIGRT_29",
/* 62 */ "SIGRT_30",
/* 63 */ "SIGRT_31",
/* 64 */ "SIGRTMAX",
};
const char *dispStr[] = {
@ -113,50 +112,89 @@ extern "C" uintptr_t _sig_linux_trampoline_start, _sig_linux_trampoline_end;
static const struct
{
int linuxSignal;
int nativeSignal;
} signalMapping[] = {
{linux_SIGHUP, SIGHUP},
{linux_SIGINT, SIGINT},
{linux_SIGQUIT, SIGQUIT},
{linux_SIGILL, SIGILL},
{linux_SIGTRAP, SIGTRAP},
{linux_SIGABRT, SIGABRT},
{linux_SIGBUS, SIGBUS},
{linux_SIGFPE, SIGFPE},
{linux_SIGKILL, SIGKILL},
{linux_SIGUSR1, SIGUSR1},
{linux_SIGSEGV, SIGSEGV},
{linux_SIGUSR2, SIGUSR2},
{linux_SIGPIPE, SIGPIPE},
{linux_SIGALRM, SIGALRM},
{linux_SIGTERM, SIGTERM},
{linux_SIGSTKFLT, SIGRSV1},
{linux_SIGCHLD, SIGCHLD},
{linux_SIGCONT, SIGCONT},
{linux_SIGSTOP, SIGSTOP},
{linux_SIGTSTP, SIGTSTP},
{linux_SIGTTIN, SIGTTIN},
{linux_SIGTTOU, SIGTTOU},
{linux_SIGURG, SIGURG},
{linux_SIGXCPU, SIGXCPU},
{linux_SIGXFSZ, SIGXFSZ},
{linux_SIGVTALRM, SIGVTALRM},
{linux_SIGPROF, SIGPROF},
{linux_SIGPOLL, SIGPOLL},
{linux_SIGPWR, SIGRSV2},
{linux_SIGSYS, SIGSYS},
{linux_SIGUNUSED, SIGSYS},
Signals Signal;
SignalDispositions Disposition;
} SignalDisposition[] = {
{SIGHUP, SIG_TERM},
{SIGINT, SIG_TERM},
{SIGQUIT, SIG_TERM},
{SIGILL, SIG_CORE},
{SIGTRAP, SIG_CORE},
{SIGABRT, SIG_CORE},
{SIGBUS, SIG_CORE},
{SIGFPE, SIG_CORE},
{SIGKILL, SIG_TERM},
{SIGUSR1, SIG_TERM},
{SIGSEGV, SIG_CORE},
{SIGUSR2, SIG_TERM},
{SIGPIPE, SIG_TERM},
{SIGALRM, SIG_TERM},
{SIGTERM, SIG_TERM},
{SIGCOMP1, SIG_IGN},
{SIGCHLD, SIG_IGN},
{SIGCONT, SIG_CONT},
{SIGSTOP, SIG_STOP},
{SIGTSTP, SIG_STOP},
{SIGTTIN, SIG_STOP},
{SIGTTOU, SIG_STOP},
{SIGURG, SIG_IGN},
{SIGXCPU, SIG_CORE},
{SIGXFSZ, SIG_CORE},
{SIGVTALRM, SIG_TERM},
{SIGPROF, SIG_TERM},
{SIGCOMP2, SIG_IGN},
{SIGPOLL, SIG_TERM},
{SIGCOMP3, SIG_IGN},
{SIGSYS, SIG_CORE},
{SIGRTMIN, SIG_IGN},
{SIGRT_1, SIG_IGN},
{SIGRT_2, SIG_IGN},
{SIGRT_3, SIG_IGN},
{SIGRT_4, SIG_IGN},
{SIGRT_5, SIG_IGN},
{SIGRT_6, SIG_IGN},
{SIGRT_7, SIG_IGN},
{SIGRT_8, SIG_IGN},
{SIGRT_9, SIG_IGN},
{SIGRT_10, SIG_IGN},
{SIGRT_11, SIG_IGN},
{SIGRT_12, SIG_IGN},
{SIGRT_13, SIG_IGN},
{SIGRT_14, SIG_IGN},
{SIGRT_15, SIG_IGN},
{SIGRT_16, SIG_IGN},
{SIGRT_17, SIG_IGN},
{SIGRT_18, SIG_IGN},
{SIGRT_19, SIG_IGN},
{SIGRT_20, SIG_IGN},
{SIGRT_21, SIG_IGN},
{SIGRT_22, SIG_IGN},
{SIGRT_23, SIG_IGN},
{SIGRT_24, SIG_IGN},
{SIGRT_25, SIG_IGN},
{SIGRT_26, SIG_IGN},
{SIGRT_27, SIG_IGN},
{SIGRT_28, SIG_IGN},
{SIGRT_29, SIG_IGN},
{SIGRT_30, SIG_IGN},
{SIGRT_31, SIG_IGN},
{SIGRTMAX, SIG_IGN},
};
static_assert(linux_SIGUNUSED == SIGNAL_MAX);
SignalDispositions GetDefaultSignalDisposition(Signals sig)
{
foreach (auto var in SignalDisposition)
{
if (var.Signal == sig)
return var.Disposition;
}
#define CTLif(x) ConvertToLinuxIfNecessary(x)
#define CTNif(x) ConvertToNativeIfNecessary(x)
#define CSigTLif(x) ConvertSigsetToLinuxIfNecessary(x)
#define CSigTNif(x) ConvertSigsetToNativeIfNecessary(x)
error("Invalid signal: %d", sig);
return SIG_TERM;
}
/* TODO: CTLif & CTNif may need optimization */
/* syscalls/linux.cpp */
extern int ConvertSignalToLinux(Signals sig);
namespace Tasking
{
@ -165,86 +203,10 @@ namespace Tasking
return ((PCB *)ctx)->Info.Compatibility == Linux;
}
int Signal::ConvertToLinuxIfNecessary(int sig)
{
if (!LinuxSig())
{
debug("Not linux sig: %d", sig);
return sig;
}
foreach (auto &mapping in signalMapping)
{
if (mapping.nativeSignal == sig)
{
// debug("Converted %d to %d", sig, mapping.linuxSignal);
return mapping.linuxSignal;
}
}
return -1;
}
int Signal::ConvertToNativeIfNecessary(int sig)
{
if (!LinuxSig())
{
debug("Not native sig: %d", sig);
return sig;
}
foreach (auto &mapping in signalMapping)
{
if (mapping.linuxSignal == sig)
{
// debug("Converted %d to %d", sig, mapping.nativeSignal);
return mapping.nativeSignal;
}
}
return -1;
}
sigset_t Signal::ConvertSigsetToLinuxIfNecessary(sigset_t sig)
{
if (!LinuxSig())
{
debug("Not linux sigset: %#lx", sig);
return 0;
}
sigset_t ret = 0;
for (int i = 0; i < SIGNAL_MAX; i++)
{
if (sig & ToFlag(i))
ret |= ToFlag(CTLif(i));
}
return ret;
}
sigset_t Signal::ConvertSigsetToNativeIfNecessary(sigset_t sig)
{
if (!LinuxSig())
{
debug("Not native sigset: %#lx", sig);
return 0;
}
sigset_t ret = 0;
for (int i = 0; i < linux_SIGUNUSED; i++)
{
if (sig & ToFlag(i))
ret |= ToFlag(CTNif(i));
}
return ret;
}
int Signal::MakeExitCode(int sig)
int Signal::MakeExitCode(Signals sig)
{
if (this->LinuxSig())
return 128 + sig;
return 128 + ConvertSignalToLinux(sig);
else
return 100 + sig;
}
@ -293,7 +255,7 @@ namespace Tasking
}
case Windows:
{
fixme("Windows compatibility");
assert(!"Windows compatibility not implemented");
break;
}
default:
@ -304,18 +266,18 @@ namespace Tasking
/* ------------------------------------------------------ */
int Signal::AddWatcher(Signal *who, int sig)
int Signal::AddWatcher(Signal *who, Signals sig)
{
SmartLock(SignalLock);
SignalInfo info;
info.sig = sig;
info.val.sival_ptr = who;
SmartLock(SignalLock);
Watchers.push_back(info);
return 0;
}
int Signal::RemoveWatcher(Signal *who, int sig)
int Signal::RemoveWatcher(Signal *who, Signals sig)
{
SmartLock(SignalLock);
forItr(itr, Watchers)
@ -330,42 +292,73 @@ namespace Tasking
return -ENOENT;
}
int Signal::AddSignal(int sig, union sigval val)
int Signal::AddSignal(Signals sig, union sigval val, pid_t tid)
{
SmartLock(SignalLock);
SignalInfo info{.sig = sig, .val = val};
SignalQueue.push_back(info);
SignalInfo info{.sig = sig, .val = val, .tid = tid};
Queue.push_back(info);
return 0;
}
int Signal::RemoveSignal(int sig)
int Signal::RemoveSignal(Signals sig)
{
SmartLock(SignalLock);
forItr(itr, SignalQueue)
{
if (itr->sig == sig)
{
SignalQueue.erase(itr);
return 0;
}
}
return -ENOENT;
size_t n = Queue.remove_if([sig](SignalInfo &info)
{ return info.sig == sig; });
debug("Removed %d signals", n);
return n ? 0 : -ENOENT;
}
bool Signal::HandleSignal(CPU::TrapFrame *tf)
Signal::SignalInfo Signal::GetAvailableSignal(void *thread)
{
SmartLock(SignalLock);
if (SignalQueue.empty())
return false;
forItr(itr, Queue)
{
// if (GlobalMask.test(itr->sig - 1))
// {
// debug("Signal %s is blocked by global mask",
// sigStr[itr->sig]);
// continue;
// }
if (((TCB *)thread)->Signals.Mask.test(itr->sig - 1))
{
debug("Signal %s is blocked by thread mask",
sigStr[itr->sig]);
continue;
}
if (((TCB *)thread)->ID != itr->tid && itr->tid != -1)
{
debug("Signal %s is not for this thread",
sigStr[itr->sig]);
continue;
}
assert(sa[itr->sig].sa_handler.Disposition != SAD_IGN);
assert(sa[itr->sig].sa_handler.Disposition != SAD_DFL);
Queue.erase(itr);
debug("Signal %s is available", sigStr[itr->sig]);
return *itr;
}
debug("No signal available");
return {};
}
bool Signal::HandleSignal(CPU::TrapFrame *tf, void *thread)
{
/* We don't want to do this in kernel mode */
if (unlikely(tf->cs != GDT_USER_CODE))
if (tf->cs != GDT_USER_CODE)
return false;
debug("We have %d signals to handle", SignalQueue.size());
if (Queue.empty())
return false;
SignalInfo sigI = SignalQueue.front();
SignalQueue.erase(SignalQueue.begin());
debug("We have %d signals to handle", Queue.size());
SmartLock(SignalLock);
SignalInfo sigI = GetAvailableSignal(thread);
if (sigI.sig == SIG_NULL)
return false;
uintptr_t _p_rsp = ((PCB *)ctx)->PageTable->Get(tf->rsp);
uint64_t paRsp = _p_rsp;
@ -388,10 +381,11 @@ namespace Tasking
si.GSBase = CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
si.FSBase = CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE);
si.ShadowGSBase = CPU::x64::rdmsr(CPU::x64::MSR_SHADOW_GS_BASE);
si.SignalMask = ((TCB *)thread)->Signals.Mask.to_ulong();
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
debug("gs: %#lx fs: %#lx shadow: %#lx",
si.GSBase, si.FSBase, si.ShadowGSBase);
si.SignalMask = SignalMask.load();
si.Compatibility = ((PCB *)ctx)->Info.Compatibility;
/* Copy the stack info */
uint64_t *pRsp = (uint64_t *)(paRsp - sizeof(StackInfo));
@ -400,31 +394,56 @@ namespace Tasking
/* Set the handler address */
pRsp--; /* Alignment */
pRsp--;
*pRsp = uint64_t(SignalAction[sigI.sig].__sa_handler.sa_handler);
*pRsp = uint64_t(sa[sigI.sig].sa_handler.Handler);
assert(!((uintptr_t)pRsp & 0xF));
int cSig = LinuxSig() ? ConvertSignalToLinux((Signals)sigI.sig) : sigI.sig;
#ifdef DEBUG
DumpData("Stack Data", (void *)pRsp,
paRsp - uint64_t(pRsp));
debug("initial stack tf->rsp: %#lx after: %#lx",
tf->rsp, uint64_t(vRsp));
debug("sig: %d -> %d", sigI.sig, CTLif(sigI.sig));
debug("sig: %d -> %d", sigI.sig, cSig);
#endif
tf->rsp = uint64_t(vRsp);
tf->rip = uint64_t(TrampAddr);
tf->rdi = CTLif(sigI.sig);
tf->rsi = uint64_t(sigI.val.sival_ptr);
/* void func(int signo); */
/* void func(int signo, siginfo_t *info, void *context); */
tf->rdi = cSig;
if (sa[sigI.sig].Flags & SA_SIGINFO)
{
fixme("SA_SIGINFO not implemented");
siginfo_t *info = 0;
void *context = 0;
tf->rsi = uint64_t(info);
tf->rdx = uint64_t(context);
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
else
{
tf->rsi = 0;
tf->rdx = 0;
tf->rcx = 0;
tf->r8 = 0;
tf->r9 = 0;
}
((TCB *)thread)->Signals.Mask = sa[sigI.sig].Mask;
assert(TrampAddr != nullptr);
return true;
}
void Signal::RestoreHandleSignal(SyscallsFrame *sf)
void Signal::RestoreHandleSignal(SyscallsFrame *sf, void *thread)
{
SmartLock(SignalLock);
debug("Restoring signal handler");
SmartLock(SignalLock);
gsTCB *gs = (gsTCB *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
uint64_t *sp = (uint64_t *)((PCB *)ctx)->PageTable->Get(gs->TempStack);
sp++; /* Alignment */
@ -454,7 +473,7 @@ namespace Tasking
sf->ReturnAddress = si->tf.rip;
gs->TempStack = (void *)si->tf.rsp;
SignalMask.store(si->SignalMask);
((TCB *)thread)->Signals.Mask = si->SignalMask;
CPU::x64::fxrstor(&si->fx);
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, si->ShadowGSBase);
@ -468,86 +487,83 @@ namespace Tasking
/* Return because we will restore at sysretq */
}
sigset_t Signal::Block(sigset_t sig)
int Signal::SetAction(Signals sig, const SignalAction *act)
{
SmartLock(SignalLock);
sig = CSigTNif(sig);
sigset_t oldMask = SignalMask.fetch_or(sig);
debug("%#lx -> %#lx", oldMask, SignalMask);
return CSigTLif(oldMask);
}
sigset_t Signal::Unblock(sigset_t sig)
{
SmartLock(SignalLock);
sig = CSigTNif(sig);
sigset_t oldMask = SignalMask.fetch_and(~sig);
debug("%#lx -> %#lx", oldMask, SignalMask);
return CSigTLif(oldMask);
}
sigset_t Signal::SetMask(sigset_t sig)
{
SmartLock(SignalLock);
sig = CSigTNif(sig);
sigset_t oldMask = SignalMask.exchange(sig);
debug("%#lx -> %#lx", oldMask, SignalMask);
return CSigTLif(oldMask);
}
int Signal::SetAction(int sig, const sigaction act)
{
SmartLock(SignalLock);
int nSig = CTNif(sig);
if ((size_t)nSig > sizeof(SignalAction) / sizeof(SignalAction[0]))
if ((size_t)sig > sizeof(sa) / sizeof(sa[0]))
{
debug("Invalid signal: %d (req %d)", nSig, sig);
debug("Invalid signal: %d", sig);
return -EINVAL;
}
SignalAction[nSig].__sa_handler.sa_handler = act.__sa_handler.sa_handler;
SignalAction[nSig].sa_mask = act.sa_mask;
SignalAction[nSig].sa_flags = act.sa_flags;
if ((long)act->sa_handler.Disposition == SAD_IGN)
{
Disposition[sig] = SIG_IGN;
debug("Set disposition for %s to SIG_IGN", sigStr[sig]);
debug("Discarding pending signals %s", sigStr[sig]);
bool found = false;
forItr(itr, Queue)
{
if (itr->sig == sig)
{
Queue.erase(itr);
found = true;
break;
}
}
if (!found)
{
debug("No pending signal %s", sigStr[sig]);
}
}
if ((long)act->sa_handler.Disposition == SAD_DFL)
{
Disposition[sig] = GetDefaultSignalDisposition(sig);
debug("Set disposition for %s to %s (default)", sigStr[sig],
dispStr[Disposition[sig]]);
}
sa[sig].sa_handler.Handler = act->sa_handler.Handler;
sa[sig].Mask = act->Mask;
sa[sig].Flags = act->Flags;
sa[sig].Restorer = act->Restorer;
debug("Set action for %s with handler %#lx, mask %#lx and flags %#lx",
LinuxSig() ? lSigStr[nSig] : sigStr[nSig],
SignalAction[nSig].__sa_handler.sa_handler,
SignalAction[nSig].sa_mask,
SignalAction[nSig].sa_flags);
sigStr[sig], sa[sig].sa_handler.Handler, sa[sig].Mask, sa[sig].Flags);
return 0;
}
int Signal::GetAction(int sig, sigaction *act)
int Signal::GetAction(Signals sig, SignalAction *act)
{
SmartLock(SignalLock);
int nSig = CTNif(sig);
if ((size_t)nSig > sizeof(SignalAction) / sizeof(SignalAction[0]))
if ((size_t)sig > sizeof(sa) / sizeof(sa[0]))
{
debug("Invalid signal: %d (req %d)", nSig, sig);
debug("Invalid signal: %d", sig);
return -EINVAL;
}
act->__sa_handler.sa_handler = SignalAction[nSig].__sa_handler.sa_handler;
act->sa_mask = SignalAction[nSig].sa_mask;
act->sa_flags = SignalAction[nSig].sa_flags;
act->sa_handler.Handler = sa[sig].sa_handler.Handler;
act->Mask = sa[sig].Mask;
act->Flags = sa[sig].Flags;
act->Restorer = sa[sig].Restorer;
debug("Got action for %s with handler %#lx, mask %#lx and flags %#lx",
LinuxSig() ? lSigStr[nSig] : sigStr[nSig],
SignalAction[nSig].__sa_handler.sa_handler,
SignalAction[nSig].sa_mask,
SignalAction[nSig].sa_flags);
sigStr[sig], sa[sig].sa_handler.Handler, sa[sig].Mask, sa[sig].Flags);
return 0;
}
int Signal::SendSignal(int sig, union sigval val)
int Signal::SendSignal(Signals sig, sigval val, pid_t tid)
{
SmartLock(SignalLock);
PCB *pcb = (PCB *)ctx;
int nSig = CTNif(sig);
LastSignal = (Signals)nSig;
LastSignal = sig;
debug("Sending signal %s to %s(%d)",
sigStr[nSig], pcb->Name, pcb->ID);
sigStr[sig], pcb->Name, pcb->ID);
if (SignalAction[nSig].__sa_handler.sa_handler)
if (sa[sig].sa_handler.Handler)
{
if (pcb->Security.ExecutionMode == Kernel)
{
@ -555,35 +571,51 @@ namespace Tasking
return -EINVAL;
}
debug("sa_handler: %#lx",
SignalAction[nSig].__sa_handler.sa_handler);
debug("Adding signal %s to queue", sigStr[nSig]);
if (sa[sig].sa_handler.Disposition == SAD_IGN)
{
debug("Ignoring signal %s", sigStr[sig]);
return 0;
}
debug("sa_handler: %#lx", sa[sig].sa_handler.Handler);
debug("Adding signal %s to queue", sigStr[sig]);
goto CompleteSignal;
}
else
{
debug("No handler for signal %s", sigStr[sig]);
}
debug("Signal disposition: %s", dispStr[sigDisp[nSig]]);
switch (sigDisp[nSig])
if (thisThread->Signals.Mask.test(sig - 1))
{
debug("Signal %s is blocked by thread mask",
sigStr[sig]);
return 0;
}
debug("Signal disposition: %s", dispStr[Disposition[sig]]);
switch (Disposition[sig])
{
case SIG_TERM:
{
if (unlikely(pcb->Security.IsCritical))
{
debug("Critical process %s received signal %s(%d): Terminated",
pcb->Name, sigStr[nSig], nSig);
pcb->Name, sigStr[sig], sig);
// int3;
}
pcb->SetExitCode(MakeExitCode(nSig));
pcb->SetExitCode(MakeExitCode(sig));
debug("We have %d watchers", this->Watchers.size());
if (this->Watchers.size() > 0)
pcb->SetState(Zombie);
else
pcb->SetState(Terminated);
break;
return 0;
}
case SIG_IGN:
{
debug("Ignoring signal %d", nSig);
debug("Ignoring signal %d", sig);
return 0;
}
case SIG_CORE:
@ -593,27 +625,31 @@ namespace Tasking
if (unlikely(pcb->Security.IsCritical))
{
debug("Critical process %s received signal %s(%d): Core dumped",
pcb->Name, sigStr[nSig], nSig);
pcb->Name, sigStr[sig], sig);
// int3;
}
pcb->SetExitCode(MakeExitCode(nSig));
pcb->SetExitCode(MakeExitCode(sig));
debug("We have %d watchers", this->Watchers.size());
if (this->Watchers.size() > 0)
pcb->SetState(CoreDump);
else
pcb->SetState(Terminated);
break;
return 0;
}
case SIG_STOP:
{
debug("Stopping process %s(%d) with signal %s(%d)",
pcb->Name, pcb->ID, sigStr[sig], sig);
pcb->SetState(Stopped);
break;
return 0;
}
case SIG_CONT:
{
debug("Continuing process %s(%d) with signal %s(%d)",
pcb->Name, pcb->ID, sigStr[sig], sig);
pcb->SetState(Ready);
break;
return 0;
}
default:
assert(!"Invalid signal disposition");
@ -624,14 +660,14 @@ namespace Tasking
if (pcb->Security.ExecutionMode == Kernel)
{
debug("Kernel process %s received signal %s(%d)! Ignoring... (with exceptions)",
pcb->Name, sigStr[nSig], nSig);
pcb->Name, sigStr[sig], sig);
return 0;
}
this->InitTrampoline();
debug("Signal %s(%d) completed", sigStr[nSig], nSig);
if (sigDisp[nSig] != SIG_IGN)
debug("Signal %s(%d) completed", sigStr[sig], sig);
if (Disposition[sig] != SIG_IGN)
{
foreach (auto info in Watchers)
{
@ -645,27 +681,24 @@ namespace Tasking
}
debug("Adding signal to queue");
SignalQueue.push_back({.sig = nSig, .val = val});
Queue.push_back({.sig = sig, .val = val, .tid = tid});
return 0;
}
int Signal::WaitAnySignal()
{
/* Sleep until a signal that terminated or invokes
the signal catch function */
debug("Waiting for any signal");
size_t oldSize = SignalQueue.size();
size_t oldSize = Queue.size();
Reset:
while (SignalQueue.size() == oldSize)
while (Queue.size() == oldSize)
TaskManager->Yield();
if (SignalQueue.size() > oldSize)
if (Queue.size() > oldSize)
{
debug("Added signal to queue %d > %d",
SignalQueue.size(), oldSize);
oldSize = SignalQueue.size();
Queue.size(), oldSize);
oldSize = Queue.size();
goto Reset;
}
@ -673,77 +706,66 @@ namespace Tasking
return -EINTR;
}
bool Signal::HasPendingSignal()
{
return !SignalQueue.empty();
}
int Signal::WaitSignal(int sig, union sigval *val)
int Signal::WaitSignal(Signals sig, union sigval *val)
{
assert(!"WaitSignal not implemented");
return 0;
}
int Signal::WaitSignalTimeout(int sig, union sigval *val, uint64_t timeout)
int Signal::WaitSignalTimeout(Signals sig, union sigval *val, uint64_t timeout)
{
assert(!"WaitSignalTimeout not implemented");
return 0;
}
Signal::Signal(void *ctx)
Signal::Signal(void *_ctx)
{
assert(ctx != nullptr);
this->ctx = ctx;
assert(_ctx != nullptr);
this->ctx = _ctx;
sigDisp[SIG_NULL] = SIG_IGN;
sigDisp[SIGABRT] = SIG_CORE;
sigDisp[SIGALRM] = SIG_TERM;
sigDisp[SIGBUS] = SIG_CORE;
sigDisp[SIGCHLD] = SIG_IGN;
sigDisp[SIGCONT] = SIG_CONT;
sigDisp[SIGFPE] = SIG_CORE;
sigDisp[SIGHUP] = SIG_TERM;
sigDisp[SIGILL] = SIG_CORE;
sigDisp[SIGINT] = SIG_TERM;
sigDisp[SIGKILL] = SIG_TERM;
sigDisp[SIGPIPE] = SIG_TERM;
sigDisp[SIGQUIT] = SIG_TERM;
sigDisp[SIGSEGV] = SIG_CORE;
sigDisp[SIGSTOP] = SIG_STOP;
sigDisp[SIGTERM] = SIG_TERM;
sigDisp[SIGTSTP] = SIG_STOP;
sigDisp[SIGTTIN] = SIG_STOP;
sigDisp[SIGTTOU] = SIG_STOP;
sigDisp[SIGUSR1] = SIG_TERM;
sigDisp[SIGUSR2] = SIG_TERM;
sigDisp[SIGPOLL] = SIG_TERM;
sigDisp[SIGPROF] = SIG_TERM;
sigDisp[SIGSYS] = SIG_CORE;
sigDisp[SIGTRAP] = SIG_CORE;
sigDisp[SIGURG] = SIG_IGN;
sigDisp[SIGVTALRM] = SIG_TERM;
sigDisp[SIGXCPU] = SIG_CORE;
sigDisp[SIGXFSZ] = SIG_CORE;
// for (int i = 1; i < SIGNAL_MAX; i++)
// Disposition[i] = GetDefaultSignalDisposition(i);
#ifdef DEBUG
static int once = 0;
if (!once++)
{
if (LinuxSig())
{
for (int i = 0; i <= linux_SIGUNUSED; i++)
debug("%s: %s",
lSigStr[i],
dispStr[sigDisp[i]]);
}
else
{
for (int i = 0; i < SIGNAL_MAX; i++)
debug("%s: %s",
sigStr[i],
dispStr[sigDisp[i]]);
}
for (int i = 1; i < SIGNAL_MAX; i++)
debug("%s: %s",
sigStr[i],
dispStr[Disposition[(Signals)i]]);
}
#endif
}
Signal::~Signal() {}
sigset_t ThreadSignal::Block(sigset_t sig)
{
sigset_t oldMask = Mask.to_ulong();
Mask |= sig;
debug("%#lx -> %#lx", oldMask, Mask);
return oldMask;
}
sigset_t ThreadSignal::Unblock(sigset_t sig)
{
sigset_t oldMask = Mask.to_ulong();
Mask &= ~sig;
debug("%#lx -> %#lx", oldMask, Mask);
return oldMask;
}
sigset_t ThreadSignal::SetMask(sigset_t sig)
{
sigset_t oldMask = Mask.to_ulong();
Mask = sig;
debug("%#lx -> %#lx", oldMask, Mask);
return oldMask;
}
sigset_t ThreadSignal::GetMask()
{
return Mask.to_ulong();
}
}

View File

@ -64,7 +64,7 @@ namespace Tasking
{
int TCB::SendSignal(int sig)
{
return this->Parent->Signals->SendSignal(sig);
return this->Parent->Signals.SendSignal((enum Signals)sig, {0}, this->ID);
}
void TCB::SetState(TaskState state)
@ -420,6 +420,7 @@ namespace Tasking
TaskArchitecture Architecture,
TaskCompatibility Compatibility,
bool ThreadNotReady)
: Signals(Parent->Signals)
{
debug("+ %#lx", this);
@ -440,6 +441,14 @@ namespace Tasking
this->ctx = ctx;
this->ID = (TID)this->Parent->ID + (TID)this->Parent->Threads.size();
if (Compatibility == TaskCompatibility::Linux)
{
if (Parent->Threads.size() == 0)
this->Linux.tgid = Parent->ID;
else
this->Linux.tgid = Parent->Threads.front()->Linux.tgid;
}
if (this->Name)
delete[] this->Name;