faulthandler: Restore the old sigaltstack during teardown (#777)

diff --git a/Misc/ACKS b/Misc/ACKS
index c99aeaa..2056efe 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
Binary files differ
diff --git a/Misc/NEWS b/Misc/NEWS
index 97c45d4..8cc8b9f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -287,6 +287,9 @@
 Library
 -------
 
+- bpo-29884: faulthandler: Restore the old sigaltstack during teardown.
+  Patch by Christophe Zeitouny.
+
 - bpo-25455: Fixed crashes in repr of recursive buffered file-like objects.
 
 - bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 4a03eaf..fc9490d 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -124,6 +124,7 @@
 
 #ifdef HAVE_SIGALTSTACK
 static stack_t stack;
+static stack_t old_stack;
 #endif
 
 
@@ -1317,7 +1318,7 @@
     stack.ss_size = SIGSTKSZ;
     stack.ss_sp = PyMem_Malloc(stack.ss_size);
     if (stack.ss_sp != NULL) {
-        err = sigaltstack(&stack, NULL);
+        err = sigaltstack(&stack, &old_stack);
         if (err) {
             PyMem_Free(stack.ss_sp);
             stack.ss_sp = NULL;
@@ -1373,6 +1374,20 @@
     faulthandler_disable();
 #ifdef HAVE_SIGALTSTACK
     if (stack.ss_sp != NULL) {
+        /* Fetch the current alt stack */
+        stack_t current_stack;
+        if (sigaltstack(NULL, &current_stack) == 0) {
+            if (current_stack.ss_sp == stack.ss_sp) {
+                /* The current alt stack is the one that we installed.
+                 It is safe to restore the old stack that we found when
+                 we installed ours */
+                sigaltstack(&old_stack, NULL);
+            } else {
+                /* Someone switched to a different alt stack and didn't
+                   restore ours when they were done (if they're done).
+                   There's not much we can do in this unlikely case */
+            }
+        }
         PyMem_Free(stack.ss_sp);
         stack.ss_sp = NULL;
     }