This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
hurd: Fix longjmp from signal handler
- From: Samuel Thibault <samuel dot thibault at gnu dot org>
- To: libc-alpha at sourceware dot org, roland at hack dot frob dot com, bug-hurd at gnu dot org
- Date: Tue, 20 Oct 2015 22:24:12 +0200
- Subject: hurd: Fix longjmp from signal handler
- Authentication-results: sourceware.org; auth=none
Hello,
The patch below fixes a corner case of signals: when longjumping from a
signal handler, the code currently restores the reply port used by the
main code. But since we possibly longjmp over a pending RPC, we should
rather just kill that reply port, which will thus get recreated on next
RPC. Otherwise, the next RPC will try to use it and probably receive a
message that was for the interrupted RPC, and thus produce a -301 error
(EMIG_REPLY_MISMATCH)... For instance, the testcase below always show
that mach_port_destroy returns a -301 error: it actually gets the reply
message of the raise call itself...
Roland, do you agree on this?
Samuel
#include <mach.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
void handle(int sig) {
fprintf(stderr, "got it\n");
siglongjmp(jb, sig);
}
int main(void)
{
int res;
int i;
int err = 0;
signal(SIGBUS, handle);
if (!(res = sigsetjmp(jb, 1)))
{
res = raise(SIGBUS);
if (res)
perror("raise");
}
else
{
res = mach_port_destroy(__mach_task_self(), MACH_PORT_NULL);
if (res)
fprintf(stderr,"%d\n", res);
}
return 0;
}
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c
index 3a62fb5..e535c4a 100644
--- a/hurd/sigunwind.c
+++ b/hurd/sigunwind.c
@@ -50,7 +50,8 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
*reply_port = MACH_PORT_DEAD;
__mach_port_destroy (__mach_task_self (), port);
}
- *reply_port = scp->sc_reply_port;
+ if (scp->sc_reply_port)
+ __mach_port_destroy (__mach_task_self (), scp->sc_reply_port);
}
__spin_lock (&ss->lock);