Patchwork hurd: Fix longjmp from signal handler

login
register
mail settings
Submitter Samuel Thibault
Date Oct. 20, 2015, 8:24 p.m.
Message ID <20151020202412.GC2752@var.home>
Download mbox | patch
Permalink /patch/9281/
State New
Headers show

Comments

Samuel Thibault - Oct. 20, 2015, 8:24 p.m.
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;
}

Patch

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);