summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--init/init.c8
-rw-r--r--init/stubs.c141
2 files changed, 88 insertions, 61 deletions
diff --git a/init/init.c b/init/init.c
index 3ec1270b..70453a90 100644
--- a/init/init.c
+++ b/init/init.c
@@ -1,6 +1,6 @@
/* Start and maintain hurd core servers and system run state
- Copyright (C) 1993,94,95,96,97,98,99 Free Software Foundation, Inc.
+ Copyright (C) 1993,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
The GNU Hurd is free software; you can redistribute it and/or modify
@@ -1061,7 +1061,8 @@ frob_kernel_process (void)
pid_t child_pid; /* PID of the child we run */
task_t child_task; /* and its (original) task port */
-error_t send_signal (mach_port_t msgport, int signal, mach_port_t refport);
+error_t send_signal (mach_port_t msgport, int signal, mach_port_t refport,
+ mach_msg_timeout_t);
static void launch_something (const char *why);
@@ -1152,7 +1153,8 @@ process_signal (int signo)
error (0, err, "proc_getmsgport");
else
{
- err = send_signal (msgport, signo, task); /* Avoids blocking. */
+ err = send_signal (msgport, signo, task,
+ 500); /* Block only half a second. */
mach_port_deallocate (mach_task_self (), msgport);
if (err)
{
diff --git a/init/stubs.c b/init/stubs.c
index fd803f97..0e6bfbc2 100644
--- a/init/stubs.c
+++ b/init/stubs.c
@@ -1,5 +1,5 @@
/* By-hand stubs for some RPC calls
- Copyright (C) 1994, 1996, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1994,96,99,2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -17,8 +17,9 @@
#include <stdlib.h>
#include <hurd/hurd_types.h>
-#include <mach/message.h>
+#include <mach.h>
#include <string.h>
+#include <assert.h>
/* From hurd/msg.defs: */
#define RPCID_SIG_POST 23000
@@ -29,11 +30,14 @@
error_t
send_signal (mach_port_t msgport,
int signal,
- mach_port_t refport)
+ mach_port_t refport,
+ mach_msg_timeout_t timeout)
{
error_t err;
- static struct
+ /* This message buffer might be modified by mach_msg in some error cases,
+ so we cannot safely reuse a static buffer. */
+ struct
{
mach_msg_header_t head;
mach_msg_type_t signaltype;
@@ -44,63 +48,84 @@ send_signal (mach_port_t msgport,
mach_port_t refport;
}
message =
+ {
{
- {
- /* Message header: */
- (MACH_MSGH_BITS_COMPLEX
- | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
- MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
- sizeof message, /* msgh_size */
- 0, /* msgh_remote_port */
- MACH_PORT_NULL, /* msgh_local_port */
- 0, /* msgh_seqno */
- RPCID_SIG_POST, /* msgh_id */
- },
- {
- /* Type descriptor for signo */
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_inline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Signal number */
- 0,
- /* Type descriptor for sigcode */
- {
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_inline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Sigcode */
- 0,
- {
- /* Type descriptor for refport */
- MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_inline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Reference port */
- MACH_PORT_NULL,
- };
+ /* Message header: */
+ (MACH_MSGH_BITS_COMPLEX
+ | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
+ sizeof message, /* msgh_size */
+ msgport, /* msgh_remote_port */
+ MACH_PORT_NULL, /* msgh_local_port */
+ 0, /* msgh_seqno */
+ RPCID_SIG_POST, /* msgh_id */
+ },
+ {
+ /* Type descriptor for signo */
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Signal number */
+ signal,
+ /* Type descriptor for sigcode */
+ {
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Sigcode */
+ 0,
+ {
+ /* Type descriptor for refport */
+ MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Reference port */
+ refport
+ };
- message.head.msgh_remote_port = msgport;
- message.signal = signal;
- message.refport = refport;
+ err = mach_msg (&message.head,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
+ MACH_PORT_NULL, timeout, MACH_PORT_NULL);
- err = mach_msg((mach_msg_header_t *)&message,
- MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
- MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ switch (err)
+ {
+ case MACH_SEND_TIMED_OUT:
+ /* The send could not complete in time. In this error case, the
+ kernel has modified the message buffer in a pseudo-receive operation.
+ That means our COPY_SEND refs might now be MOVE_SEND refs, in
+ which case each has gained user ref accordingly. To avoid leaking
+ those refs, we must clean up the buffer. */
+ mach_msg_destroy (&message.head);
+ break;
+
+ /* These are the other codes that mean a pseudo-receive modified
+ the message buffer and we might need to clean up the send rights.
+ None of them should be possible in our usage. */
+ case MACH_SEND_INTERRUPTED:
+ case MACH_SEND_INVALID_NOTIFY:
+ case MACH_SEND_NO_NOTIFY:
+ case MACH_SEND_NOTIFY_IN_PROGRESS:
+ assert_perror (err);
+ break;
+
+ default: /* Other errors are safe to ignore. */
+ break;
+ }
return err;
}