aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/hurdsig.c15
-rw-r--r--hurd/intr-msg.c1
-rw-r--r--sysdeps/mach/hurd/mig-reply.c25
3 files changed, 20 insertions, 21 deletions
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index b3808f9..78ea59d 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -477,9 +477,18 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
if (reply)
{
/* The interrupt didn't work.
- Destroy the receive right the thread is blocked on. */
- __mach_port_destroy (__mach_task_self (), *reply);
- *reply = MACH_PORT_NULL;
+ Destroy the receive right the thread is blocked on, and
+ replace it with a dead name to keep the name from reuse until
+ the therad is done with it. To do this atomically, first
+ insert a send right, and then destroy the receive right,
+ turning the send right into a dead name. */
+ err = __mach_port_insert_right (__mach_task_self (),
+ *reply, *reply,
+ MACH_MSG_TYPE_MAKE_SEND);
+ assert_perror (err);
+ err = __mach_port_mod_refs (__mach_task_self (), *reply,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ assert_perror (err);
}
/* The system call return value register now contains
diff --git a/hurd/intr-msg.c b/hurd/intr-msg.c
index 1a086b5..716d87a 100644
--- a/hurd/intr-msg.c
+++ b/hurd/intr-msg.c
@@ -305,6 +305,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
{
/* Make sure we have a valid reply port. The one we were using
may have been destroyed by interruption. */
+ __mig_dealloc_reply_port (rcv_name);
m->header.msgh_local_port = rcv_name = __mig_get_reply_port ();
m->header.msgh_bits = msgh_bits;
option = user_option;
diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c
index 3fdee80..7ea001d 100644
--- a/sysdeps/mach/hurd/mig-reply.c
+++ b/sysdeps/mach/hurd/mig-reply.c
@@ -69,29 +69,18 @@ __mig_dealloc_reply_port (mach_port_t arg)
mach_port_t port = get_reply_port ();
set_reply_port (MACH_PORT_NULL); /* So the mod_refs RPC won't use it. */
-
- /* Normally, ARG should be the same as PORT that we store. However, if a
- signal has interrupted the RPC, the stored PORT has been deallocated and
- reset to MACH_PORT_NULL (or possibly MACH_PORT_DEAD). In this case the
- MIG routine still has the old name, which it passes to us here. We must
- not deallocate (or otherwise touch) it, since it may be already allocated
- to another port right. Fortunately MIG itself doesn't do anything with
- the reply port on errors either, other than immediately calling this
- function.
-
- And so:
- 1. Assert that things are sane, i.e. and PORT is either invalid or same
- as ARG.
- 2. Only deallocate the name if our stored PORT still names it. In that
- case we're sure the right has not been deallocated / the name reused.
- */
-
+ assert (port == arg);
if (!MACH_PORT_VALID (port))
return;
- assert (port == arg);
err = __mach_port_mod_refs (__mach_task_self (), port,
MACH_PORT_RIGHT_RECEIVE, -1);
+ if (err == KERN_INVALID_RIGHT)
+ /* It could be that during signal handling, the receive right had been
+ replaced with a dead name. */
+ err = __mach_port_mod_refs (__mach_task_self (), port,
+ MACH_PORT_RIGHT_DEAD_NAME, -1);
+
assert_perror (err);
}
weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port)