mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-27 15:04:33 +00:00
Rework signal handling code
This commit is contained in:
parent
3b1bd58a36
commit
3d1ecc3db0
@ -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:
|
||||
|
@ -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) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user