about summary refs log tree commit diff
path: root/src/libstd/sys/unix/stack_overflow.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-02-18 23:23:22 +0000
committerbors <bors@rust-lang.org>2016-02-18 23:23:22 +0000
commit8842e28be8857e8e37591e2dec469d6720c278cb (patch)
tree0993e9663e68ab676419c48fb4502d633f640788 /src/libstd/sys/unix/stack_overflow.rs
parentde366b5218974e79c4961e26f063e5fb51039745 (diff)
parent77922b817e012989ee8b0f371242e078e58b9ca1 (diff)
downloadrust-8842e28be8857e8e37591e2dec469d6720c278cb.tar.gz
rust-8842e28be8857e8e37591e2dec469d6720c278cb.zip
Auto merge of #31684 - tmiasko:alternate-stack, r=alexcrichton
Remove alternate stack with sigaltstack before unmaping it.

Also reuse existing signal stack if already set, this is especially
useful when working with sanitizers that configure alternate stack
themselves.

This change depends on SS_DISABLE recently introduced in libc crate and updates
this git submodule accordingly.
Diffstat (limited to 'src/libstd/sys/unix/stack_overflow.rs')
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index a868abbb731..1b5faf64ad6 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -46,7 +46,7 @@ mod imp {
     use super::Handler;
     use mem;
     use ptr;
-    use libc::{sigaltstack, SIGSTKSZ};
+    use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{sigaction, SIGBUS, SIG_DFL,
                SA_SIGINFO, SA_ONSTACK, sighandler_t};
     use libc;
@@ -169,13 +169,32 @@ mod imp {
     }
 
     pub unsafe fn make_handler() -> Handler {
-        let stack = get_stack();
-        sigaltstack(&stack, ptr::null_mut());
-        Handler { _data: stack.ss_sp as *mut libc::c_void }
+        let mut stack = mem::zeroed();
+        sigaltstack(ptr::null(), &mut stack);
+        // Configure alternate signal stack, if one is not already set.
+        if stack.ss_flags & SS_DISABLE != 0 {
+            stack = get_stack();
+            sigaltstack(&stack, ptr::null_mut());
+            Handler { _data: stack.ss_sp as *mut libc::c_void }
+        } else {
+            Handler { _data: ptr::null_mut() }
+        }
     }
 
     pub unsafe fn drop_handler(handler: &mut Handler) {
-        munmap(handler._data, SIGSTKSZ);
+        if !handler._data.is_null() {
+            let stack =  libc::stack_t {
+                ss_sp: ptr::null_mut(),
+                ss_flags: SS_DISABLE,
+                // Workaround for bug in MacOS implementation of sigaltstack
+                // UNIX2003 which returns ENOMEM when disabling a stack while
+                // passing ss_size smaller than MINSIGSTKSZ. According to POSIX
+                // both ss_sp and ss_size should be ignored in this case.
+                ss_size: SIGSTKSZ,
+            };
+            sigaltstack(&stack, ptr::null_mut());
+            munmap(handler._data, SIGSTKSZ);
+        }
     }
 }