hurd: Fix longjmp from signal handler
Commit Message
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;
}
@@ -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);