diff options
author | Roland McGrath <roland@gnu.org> | 2000-03-13 23:53:18 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2000-03-13 23:53:18 +0000 |
commit | d02b624edb4dc7d24d053279789559a55eca1094 (patch) | |
tree | 6b33a21da9671ca367bdb423d428e0c28f6aa350 | |
parent | a91651bf90f6f7c20164d0a30e1143b42f560cfd (diff) |
2000-03-13 Roland McGrath <roland@baalperazim.frob.com>
* stubs.c (send_signal): Make MESSAGE auto instead of static.
Take new argument TIMEOUT, passed to mach_msg instead of zero.
(send_signal): For MACH_SEND_TIMED_OUT failure, destroy the
pseudo-received message to avoid leaking send rights.
* init.c (process_signal): Pass new argument, timeout of 500 ms.
-rw-r--r-- | init/init.c | 8 | ||||
-rw-r--r-- | init/stubs.c | 141 |
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; } |