1 #include <lunaix/process.h>
2 #include <lunaix/sched.h>
3 #include <lunaix/signal.h>
4 #include <lunaix/spike.h>
5 #include <lunaix/status.h>
6 #include <lunaix/syscall.h>
8 #include <klibc/string.h>
10 extern struct scheduler sched_ctx; /* kernel/sched.c */
12 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
13 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
15 // Referenced in kernel/asm/x86/interrupt.S
19 if (!__current->sigctx.sig_pending) {
24 struct sighail* psig = &__current->sigctx;
25 struct sigact* prev_working = psig->inprogress;
26 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
28 int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
30 sigset_clear(psig->sig_pending, sig_selected);
32 struct sigact* action = &psig->signals[sig_selected];
34 if (sig_selected == 0) {
39 if (!action->sa_actor) {
40 if (sigset_test(TERMSIG, sig_selected)) {
41 terminate_proc(sig_selected | PEXITSIG);
48 ptr_t ustack = __current->ustack_top;
50 if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
55 struct proc_sig* sigframe =
56 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
60 问题是出在原本的sigframe->prev_context = __current->intr_ctx的上面
61 这个语句会被gcc在编译时,用更加高效的 rep movsl 来代替。
63 由于我们采用按需分页,所以在很多情况下,用户栈实际被分配的空间不允许我们进行完整的
64 注入,而需要走page fault handler进行动态分页。
68 假若我们的__current->intr_ctx注入了一半,然后产生page-fault中断,
69 那么这就会导致我们的__current->intr_ctx被这个page-fault中断导致的
70 上下文信息覆盖。那么当page-fault handler成功分配了一个页,返回,
71 拷贝也就得以进行。遗憾的是,只不过这次拷贝的内容和前面的拷贝是没有任何的关系
72 (因为此时的intr_ctx已经不是之前的intr_ctx了!)
73 而这就会导致我们保存在信号上下文中的进程上下文信息不完整,从而在soft_iret时
76 解决办法就是先吧intr_ctx拷贝到一个静态分配的区域里,然后再注入到用户栈。
78 static volatile struct proc_sigstate __temp_save;
79 __temp_save.proc_regs = *__current->intr_ctx;
80 memcpy(__temp_save.fxstate, __current->fxstate, 512);
82 sigframe->sig_num = sig_selected;
84 sigframe->sigact = action->sa_actor;
85 sigframe->sighand = action->sa_handler;
86 sigframe->prev_context = __temp_save;
88 action->prev = prev_working;
89 psig->inprogress = action;
95 proc_setsignal(struct proc_info* proc, int signum)
97 sigset_add(proc->sigctx.sig_pending, signum);
98 proc->sigctx.signals[signum].sender = __current->pid;
102 signal_send(pid_t pid, int signum)
104 if (signum < 0 || signum >= _SIG_NUM) {
105 __current->k_status = EINVAL;
109 pid_t sender_pid = __current->pid;
110 struct proc_info* proc;
113 proc = get_process(pid);
118 } else if (pid < -1) {
119 proc = get_process(-pid);
122 // TODO: send to all process.
123 // But I don't want to support it yet.
124 __current->k_status = EINVAL;
129 struct proc_info *pos, *n;
130 llist_for_each(pos, n, &proc->grp_member, grp_member)
132 struct sighail* sh = &pos->sigctx;
133 sigset_add(sh->sig_pending, signum);
134 sh->signals[signum].sender = sender_pid;
138 if (PROC_TERMINATED(proc->state)) {
139 __current->k_status = EINVAL;
143 sigset_add(proc->sigctx.sig_pending, signum);
144 proc->sigctx.signals[signum].sender = sender_pid;
149 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
151 memcpy(__current->fxstate, sig_ctx->prev_context.fxstate, 512);
152 // FIXME: Interrupt context is exposed to user space!
153 *__current->intr_ctx = sig_ctx->prev_context.proc_regs;
155 struct sigact* current = __current->sigctx.inprogress;
157 __current->sigctx.inprogress = current->prev;
158 current->prev = NULL;
160 __current->sigctx.inprogress = NULL;
169 __DEFINE_LXSYSCALL3(int,
178 struct sighail* sh = &__current->sigctx;
179 *oldset = sh->sig_mask;
181 if (how == _SIG_BLOCK) {
182 sigset_union(sh->sig_mask, *set);
183 } else if (how == _SIG_UNBLOCK) {
184 sigset_intersect(sh->sig_mask, ~(*set));
185 } else if (how == _SIG_SETMASK) {
191 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
195 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
197 if (signum <= 0 || signum >= _SIG_NUM) {
201 if (sigset_test(UNMASKABLE, signum)) {
205 struct sigact* sa = &__current->sigctx.signals[signum];
207 sa->sa_actor = (void*)action->sa_sigaction;
208 sa->sa_handler = (void*)action->sa_handler;
209 sigset_union(sa->sa_mask, sigset(signum));
214 __DEFINE_LXSYSCALL(int, pause)
219 __current->k_status = EINTR;
223 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
225 return signal_send(pid, signum);
228 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
230 *sigset = __current->sigctx.sig_pending;
234 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
236 sigset_t tmp = __current->sigctx.sig_mask;
237 __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
242 __current->sigctx.sig_mask = tmp;