diff --git a/regression/apps/signal_c/signal_test.c b/regression/apps/signal_c/signal_test.c
index 305eae681..a885e1398 100644
--- a/regression/apps/signal_c/signal_test.c
+++ b/regression/apps/signal_c/signal_test.c
@@ -265,6 +265,7 @@ int test_sigchld() {
// child process
printf("create a new proces successfully (pid = %d)\n", getpid());
fflush(stdout);
+ exit(0);
} else {
// parent process
wait(NULL);
@@ -274,11 +275,82 @@ int test_sigchld() {
return 0;
}
+// ============================================================================
+// Test handle signal on alternate signal stack
+// ============================================================================
+
+#define MAX_ALTSTACK_RECURSION_LEVEL 2
+
+stack_t g_old_ss;
+
+static void handle_sigpipe(int num, siginfo_t *info, void *context) {
+ static volatile int recursion_level = 0;
+ printf("Hello from SIGPIPE signal handler on the alternate signal stack (recursion_level = %d)\n",
+ recursion_level);
+
+ // save old_ss to check if we are on stack
+ stack_t old_ss;
+ sigaltstack(NULL, &old_ss);
+ g_old_ss = old_ss;
+
+ recursion_level++;
+ if (recursion_level <= MAX_ALTSTACK_RECURSION_LEVEL) {
+ raise(SIGPIPE);
+ }
+ recursion_level--;
+}
+
+#define SIGSTACKSIZE (4*4096)
+
+int test_sigaltstack() {
+ static char stack[SIGSTACKSIZE];
+ stack_t expected_ss = {
+ .ss_size = SIGSTACKSIZE,
+ .ss_sp = stack,
+ .ss_flags = 0,
+ };
+ if (sigaltstack(&expected_ss, NULL) < 0) {
+ THROW_ERROR("failed to call sigaltstack");
+ }
+ stack_t actual_ss;
+ if (sigaltstack(NULL, &actual_ss) < 0) {
+ THROW_ERROR("failed to call sigaltstack");
+ }
+ if (actual_ss.ss_size != expected_ss.ss_size
+ || actual_ss.ss_sp != expected_ss.ss_sp
+ || actual_ss.ss_flags != expected_ss.ss_flags) {
+ THROW_ERROR("failed to check the signal stack after set");
+ }
+
+ struct sigaction new_action, old_action;
+ memset(&new_action, 0, sizeof(struct sigaction));
+ memset(&old_action, 0, sizeof(struct sigaction));
+ new_action.sa_sigaction = handle_sigpipe;
+ new_action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
+ if (sigaction(SIGPIPE, &new_action, &old_action) < 0) {
+ THROW_ERROR("registering new signal handler failed");
+ }
+ if (old_action.sa_handler != SIG_DFL) {
+ THROW_ERROR("unexpected old sig handler");
+ }
+
+ raise(SIGPIPE);
+ if (g_old_ss.ss_flags != SS_ONSTACK) {
+ THROW_ERROR("check stack flags failed");
+ }
+
+ if (sigaction(SIGPIPE, &old_action, NULL) < 0) {
+ THROW_ERROR("restoring old signal handler failed");
+ }
+ return 0;
+}
+
int main() {
test_sigprocmask();
test_raise();
test_handle_sigfpe();
test_handle_sigsegv();
test_sigchld();
+ test_sigaltstack();
return 0;
}
\ No newline at end of file
diff --git a/services/libs/jinux-std/src/process/posix_thread/builder.rs b/services/libs/jinux-std/src/process/posix_thread/builder.rs
index 0f59d06df..ead10779d 100644
--- a/services/libs/jinux-std/src/process/posix_thread/builder.rs
+++ b/services/libs/jinux-std/src/process/posix_thread/builder.rs
@@ -92,7 +92,6 @@ impl PosixThreadBuilder {
let thread = Arc::new_cyclic(|thread_ref| {
let task = create_new_user_task(user_space, thread_ref.clone());
let status = ThreadStatus::Init;
- let sig_context = Mutex::new(None);
let posix_thread = PosixThread {
process,
is_main_thread,
@@ -102,7 +101,8 @@ impl PosixThreadBuilder {
credentials,
sig_mask: Mutex::new(sig_mask),
sig_queues: Mutex::new(sig_queues),
- sig_context,
+ sig_context: Mutex::new(None),
+ sig_stack: Mutex::new(None),
robust_list: Mutex::new(None),
};
diff --git a/services/libs/jinux-std/src/process/posix_thread/mod.rs b/services/libs/jinux-std/src/process/posix_thread/mod.rs
index 24528b111..414ab260e 100644
--- a/services/libs/jinux-std/src/process/posix_thread/mod.rs
+++ b/services/libs/jinux-std/src/process/posix_thread/mod.rs
@@ -3,7 +3,7 @@ use super::signal::sig_mask::SigMask;
use super::signal::sig_num::SigNum;
use super::signal::sig_queues::SigQueues;
use super::signal::signals::Signal;
-use super::signal::{SigEvents, SigEventsFilter};
+use super::signal::{SigEvents, SigEventsFilter, SigStack};
use super::{do_exit_group, Credentials, Process, TermStatus};
use crate::events::Observer;
use crate::prelude::*;
@@ -51,6 +51,7 @@ pub struct PosixThread {
/// Signal handler ucontext address
/// FIXME: This field may be removed. For glibc applications with RESTORER flag set, the sig_context is always equals with rsp.
sig_context: Mutex