diff options
-rw-r--r-- | ChangeLog | 46 | ||||
-rw-r--r-- | hurd/Makefile | 20 | ||||
-rw-r--r-- | hurd/hurd.h | 10 | ||||
-rw-r--r-- | hurd/hurd/signal.h | 62 | ||||
-rw-r--r-- | hurd/hurdsig.c | 181 | ||||
-rw-r--r-- | hurd/intr-msg.c | 151 | ||||
-rw-r--r-- | hurd/intr-rpc.defs | 12 | ||||
-rw-r--r-- | hurd/intr-rpc.h | 25 | ||||
-rw-r--r-- | hurd/thread-cancel.c | 86 | ||||
-rw-r--r-- | libc-symbols.h | 6 | ||||
-rw-r--r-- | sysdeps/generic/morecore.c | 4 | ||||
-rw-r--r-- | sysdeps/mach/hurd/alpha/trampoline.c | 47 | ||||
-rw-r--r-- | sysdeps/mach/hurd/dl-sysdep.c | 48 | ||||
-rw-r--r-- | sysdeps/mach/hurd/fork.c | 3 | ||||
-rw-r--r-- | sysdeps/mach/hurd/hppa/trampoline.c | 40 | ||||
-rw-r--r-- | sysdeps/mach/hurd/i386/trampoline.c | 42 | ||||
-rw-r--r-- | sysdeps/mach/hurd/ioctl.c | 10 | ||||
-rw-r--r-- | sysdeps/mach/hurd/kill.c | 2 | ||||
-rw-r--r-- | sysdeps/mach/hurd/mips/trampoline.c | 37 |
19 files changed, 493 insertions, 339 deletions
@@ -1,3 +1,49 @@ +Mon Aug 14 16:51:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * hurd/thread-cancel.c: New file. + * sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler): In + rpc_wait case, frob mach_msg args to set timeout on receive. + (_hurdsig_rcv_interrupted_p): Function removed. + * sysdeps/mach/hurd/alpha/trampoline.c: Likewise. + * sysdeps/mach/hurd/hppa/trampoline.c: Likewise. + * sysdeps/mach/hurd/mips/trampoline.c: Likewise. + * hurd/intr-msg.c: New file. + * hurd/hurd/signal.h (struct hurd_sigstate): New member `cancel'. + (_hurdsig_rcv_interrupted_p): Declaration removed. + (HURD_EINTR_RPC): Macro removed. + (_hurd_longjmp_thread_state, _hurd_interrupted_rpc_timeout): Declare + these. + * hurd/intr-rpc.h: New file. + * hurd/intr-rpc.defs: Just import intr-rpc.h. + * hurd/hurdsig.c (_hurd_interrupted_rpc_timeout): New variable. + (interrupted_reply_port_location): Take new flag arg; only catch + faults if it's set. + (abort_rpcs): Rename to _hurdsig_abort_rpcs; take same new flag arg. + No longer use _hurdsig_rcv_interrupted_p; instead compare PC to + &_hurd_intr_rpc_msg_in_trap. If before it, mutate state to simulate + MACH_SEND_INTERRUPTED return; on it, interrupt the operation. All + callers changed. + * hurd/hurd.h (hurd_thread_cancel, hurd_check_cancel): Declare these. + * hurd/Makefile (distribute): Remove intr-rpc.awk. + (sig): Add thread-cancel. + (transform-user-stub, transform-user-stub-output): Variables removed. + * sysdeps/mach/hurd/dl-sysdep.c: Change all RPCs from + `__hurd_intr_rpc_*' to `__*'. + (_hurd_intr_rpc_mach_msg): New function. + (_hurd_thread_sigstate): Function removed. + * sysdeps/mach/hurd/ioctl.c: Use _hurd_intr_rpc_mach_msg function, + instead of __mach_msg inside HURD_EINTR_RPC macro. + + * sysdeps/generic/morecore.c [__GNU_LIBRARY__]: Declare `__sbrk' + to take ptrdiff_t arg. + + * sysdeps/mach/hurd/fork.c: Remove _hurd_longjmp_thread_state decl. + + * sysdeps/mach/hurd/kill.c (kill_pid): Don't make `inline'. + + * libc-symbols.h [GCC >= 2.7] (strong_alias, weak_symbol, + weak_alias): Use `extern' storage class. + Wed Aug 9 14:25:35 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> * sysdeps/mach/hurd/setuid.c (__setuid): Switch the port-type and diff --git a/hurd/Makefile b/hurd/Makefile index 5e1622d87d..58bea5f1c0 100644 --- a/hurd/Makefile +++ b/hurd/Makefile @@ -28,7 +28,7 @@ headers = hurd.h $(interface-headers) \ $(addprefix hurd/,fd.h id.h port.h signal.h userlink.h \ resource.h threadvar.h) -distribute := hurdstartup.h hurdfault.h intr-rpc.awk intr-rpc.defs STATUS +distribute := hurdstartup.h hurdfault.h intr-rpc.defs STATUS # The RPC interfaces go in a separate library. interface-library := libhurduser @@ -53,7 +53,7 @@ routines = hurdstartup hurdinit \ $(sig) $(dtable) hurdinline port-cleanup sig = hurdsig hurdfault faultexc siginfo hurd-raise preempt-sig \ trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \ - thread-self + thread-self thread-cancel dtable = dtable port2fd new-fd alloc-fd intern-fd \ getdport openport \ fd-close fd-read fd-write hurdioctl ctty-input ctty-output @@ -88,25 +88,13 @@ include ../mach/Machrules include ../Rules # intr-rpc.defs defines the INTR_INTERFACE macro to make the generated RPC -# stubs send-interruptible, and to prefix them with `hurd_intr_rpc_'. +# stubs import <hurd/signal.h> and #define __mach_msg to +# _hurd_intr_rpc_mach_msg. user-MIGFLAGS += -imacros intr-rpc.defs -# Run each generated user stub through intr-rpc.awk, which will detect -# stubs __hurd_intr_rpc_% and generate the user-callable function for the -# stub: this is a wrapper which calls __hurd_intr_rpc_% inside -# HURD_EINTR_RPC. -define transform-user-stub -gawk -v call=$${call} -f $(word 2,$^) \ - $(objpfx)tmp_$${call}.c > $(objpfx)tmpi_$${call}.c; \ -rm -f $(objpfx)tmp_$${call}.c; -endef -transform-user-stub-output = tmpi - $(foreach if,$(user-interfaces),$($(if)-calls:%=$(objpfx)RPC_%.o))): \ hurd/signal.h -$(user-interfaces:%=$(objpfx)%.ustamp): intr-rpc.awk - $(objpfx)fault%.c $(objpfx)fault%.h: $(mach-srcdir)/mach/%.defs $(MIG) $(MIGFLAGS) -prefix _hurdsig_fault_ \ -server $(@:.h=.c) -sheader $(@:.c=.h) \ diff --git a/hurd/hurd.h b/hurd/hurd.h index e0ba62eede..1b4db17efe 100644 --- a/hurd/hurd.h +++ b/hurd/hurd.h @@ -286,6 +286,16 @@ extern task_t __pid2task (pid_t pid), pid2task (pid_t pid); extern thread_t hurd_thread_self (void); +/* Cancel pending operations on THREAD. If it is doing an interruptible RPC, + that RPC will now return EINTR; otherwise, the "cancelled" flag will be + set, causing the next `hurd_check_cancel' call to return nonzero or the + next interruptible RPC to return EINTR (whichever is called first). */ +extern error_t hurd_thread_cancel (thread_t thread); + +/* Test and clear the calling thread's "cancelled" flag. */ +extern int hurd_check_cancel (void); + + /* Return the io server port for file descriptor FD. This adds a Mach user reference to the returned port. On error, sets `errno' and returns MACH_PORT_NULL. */ diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index d28d1c6c11..a032313e4e 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -84,6 +84,8 @@ struct hurd_sigstate <hurd/userlink.h> for details. This member is only used by the thread itself, and always inside a critical section. */ struct hurd_userlink *active_resources; + + volatile int cancel; /* Flag set by hurd_thread_cancel. */ }; /* Linked list of states of all threads whose state has been asked for. */ @@ -253,20 +255,14 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, extern void _hurd_msgport_receive (void); -/* STATE describes a thread that had intr_port set (meaning it was inside - HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have - just completed a mach_msg_trap system call that returned - MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right - being waited on. */ - -extern int _hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, - mach_port_t *port); - /* Set up STATE with a thread state that, when resumed, is like `longjmp (_hurd_sigthread_fault_env, 1)'. */ extern void _hurd_initialize_fault_recovery_state (void *state); +/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */ + +extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value); /* Function run for SIGINFO when its action is SIG_DFL and the current process is the session leader. */ @@ -274,50 +270,10 @@ extern void _hurd_initialize_fault_recovery_state (void *state); extern void _hurd_siginfo_handler (int); -/* Perform interruptible RPC CALL on PORT. - The call should use - The args in CALL should be constant or local variable refs. - They may be evaluated many times, and must not change. - PORT must not be deallocated before this RPC is finished. */ -#define HURD_EINTR_RPC(port, call) \ - ({ \ - __label__ __do_call; /* Give this label block scope. */ \ - error_t __err; \ - struct hurd_sigstate *__ss = _hurd_self_sigstate (); \ - __do_call: \ - /* Tell the signal thread that we are doing an interruptible RPC on \ - this port. If we get a signal and should return EINTR, the signal \ - thread will set this variable to MACH_PORT_NULL. The RPC might \ - return EINTR when some other thread gets a signal, in which case we \ - want to restart our call. */ \ - __ss->intr_port = (port); \ - /* A signal may arrive here, after intr_port is set, but before the \ - mach_msg system call. The signal handler might do an interruptible \ - RPC, and clobber intr_port; then it would not be set properly when \ - we actually did send the RPC, and a later signal wouldn't interrupt \ - that RPC. So, _hurd_setup_sighandler saves intr_port in the \ - sigcontext, and sigreturn restores it. */ \ - switch (__err = (call)) \ - { \ - case EINTR: /* RPC went out and was interrupted. */ \ - case MACH_SEND_INTERRUPTED: /* RPC didn't get out. */ \ - if (__ss->intr_port != MACH_PORT_NULL) \ - /* If this signal was for us and it should interrupt calls, the \ - signal thread will have cleared SS->intr_port. Since it's not \ - cleared, the signal was for another thread, or SA_RESTART is \ - set. Restart the interrupted call. */ \ - goto __do_call; \ - /* FALLTHROUGH */ \ - case MACH_RCV_PORT_DIED: \ - /* Server didn't respond to interrupt_operation, \ - so the signal thread destroyed the reply port. */ \ - __err = EINTR; \ - break; \ - default: /* Quiet -Wswitch-enum. */ \ - } \ - __ss->intr_port = MACH_PORT_NULL; \ - __err; \ - }) \ +/* Milliseconds to wait for an interruptible RPC to return after + `interrupt_operation'. */ + +extern mach_msg_timeout_t _hurd_interrupted_rpc_timeout; /* Mask of signals that cannot be caught, blocked, or ignored. */ diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 9414c059e3..7dd2b8c2fc 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -41,6 +41,9 @@ thread_t _hurd_sigthread; /* Linked-list of per-thread signal state. */ struct hurd_sigstate *_hurd_sigstates; + +/* Timeout for RPC's after interrupt_operation. */ +mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000; static void default_sigaction (struct sigaction actions[NSIG]) @@ -76,9 +79,6 @@ _hurd_thread_sigstate (thread_t thread) __sigemptyset (&ss->pending); memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack)); ss->suspended = 0; -#ifdef noteven - __condition_init (&ss->arrived); -#endif ss->intr_port = MACH_PORT_NULL; ss->context = NULL; @@ -225,16 +225,17 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state, } /* Find the location of the MiG reply port cell in use by the thread whose - state is described by THREAD_STATE. Make sure that this location can be - set without faulting, or else return NULL. */ + state is described by THREAD_STATE. If SIGTHREAD is nonzero, make sure + that this location can be set without faulting, or else return NULL. */ static mach_port_t * -interrupted_reply_port_location (struct machine_thread_all_state *thread_state) +interrupted_reply_port_location (struct machine_thread_all_state *thread_state, + int sigthread) { mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP); - if (_hurdsig_catch_fault (SIGSEGV)) + if (sigthread && _hurdsig_catch_fault (SIGSEGV)) { assert (_hurdsig_fault_sigcode == (long int) portloc); /* Faulted trying to read the stack. */ @@ -244,7 +245,8 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state) /* Fault now if this pointer is bogus. */ *(volatile mach_port_t *) portloc = *portloc; - _hurdsig_end_catch_fault (); + if (sigthread) + _hurdsig_end_catch_fault (); return portloc; } @@ -266,12 +268,14 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state) be applied back to the thread if it might ever run again, else zero. */ static mach_port_t -abort_rpcs (struct hurd_sigstate *ss, int signo, - struct machine_thread_all_state *state, int *state_change, - mach_port_t *reply_port, mach_msg_type_name_t reply_port_type, - int untraced) +_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread, + struct machine_thread_all_state *state, int *state_change, + mach_port_t *reply_port, + mach_msg_type_name_t reply_port_type, + int untraced) { - mach_port_t msging_port; + extern const void _hurd_intr_rpc_msg_do_trap, _hurd_intr_rpc_msg_in_trap; + mach_port_t rcv_port = MACH_PORT_NULL; mach_port_t intr_port; *state_change = 0; @@ -285,71 +289,69 @@ abort_rpcs (struct hurd_sigstate *ss, int signo, receive completes immediately or aborts. */ abort_thread (ss, state, reply_port, reply_port_type, untraced); - if (_hurdsig_rcv_interrupted_p (state, &msging_port)) + if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap) { - error_t err; - - /* The RPC request message was sent and the thread was waiting for - the reply message; now the message receive has been aborted, so - the mach_msg_call will return MACH_RCV_INTERRUPTED. We must tell - the server to interrupt the pending operation. The thread must - wait for the reply message before running the signal handler (to - guarantee that the operation has finished being interrupted), so - our nonzero return tells the trampoline code to finish the message - receive operation before running the handler. */ - - err = __interrupt_operation (intr_port); - - if (err) - { - mach_port_t *reply; - - /* The interrupt didn't work. - Destroy the receive right the thread is blocked on. */ - __mach_port_destroy (__mach_task_self (), msging_port); - - /* The system call return value register now contains - MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the - call. Since we have just destroyed the receive right, the - retry will fail with MACH_RCV_INVALID_NAME. Instead, just - change the return value here to EINTR so mach_msg will not - retry and the EINTR error code will propagate up. */ - state->basic.SYSRETURN = EINTR; - *state_change = 1; - - /* If that was the thread's MiG reply port (which I think should - always be the case), clear the reply port cell so it won't be - reused. */ - reply = interrupted_reply_port_location (state); - if (reply != NULL && *reply == msging_port) - *reply = MACH_PORT_NULL; - } - - /* All threads whose RPCs were interrupted by the interrupt_operation - call above will retry their RPCs unless we clear SS->intr_port. - So we clear it for the thread taking a signal when SA_RESTART is - clear, so that its call returns EINTR. */ - if (!(ss->actions[signo].sa_flags & SA_RESTART)) - ss->intr_port = MACH_PORT_NULL; - - return err ? MACH_PORT_NULL : msging_port; + /* The thread is about to do the RPC, but hasn't yet entered + mach_msg. Mutate the thread's state so it knows not to try + the RPC. */ + MACHINE_THREAD_STATE_SET_PC (&state->basic, + &_hurd_intr_rpc_msg_in_trap); + state->basic.SYSRETURN = MACH_SEND_INTERRUPTED; + *state_change = 1; } + else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap && + /* The thread was blocked in the system call. After thread_abort, + the return value register indicates what state the RPC was in + when interrupted. */ + state->basic.SYSRETURN == MACH_RCV_INTERRUPTED) + { + /* The RPC request message was sent and the thread was waiting for + the reply message; now the message receive has been aborted, so + the mach_msg call will return MACH_RCV_INTERRUPTED. We must tell + the server to interrupt the pending operation. The thread must + wait for the reply message before running the signal handler (to + guarantee that the operation has finished being interrupted), so + our nonzero return tells the trampoline code to finish the message + receive operation before running the handler. */ + + mach_port_t *reply = interrupted_reply_port_location (state, + sigthread); + error_t err = __interrupt_operation (intr_port); + + if (err) + { + 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; + } - /* One of the following is true: - - 1. The RPC has not yet been sent. The thread will start its operation - after the signal has been handled. - - 2. The RPC has finished, but not yet cleared SS->intr_port. - The thread will clear SS->intr_port after running the handler. - - 3. The RPC request message was being sent was aborted. The mach_msg - system call will return MACH_SEND_INTERRUPTED, and HURD_EINTR_RPC will - notice the interruption (either retrying the RPC or returning EINTR). */ + /* The system call return value register now contains + MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the + call. Since we have just destroyed the receive right, the + retry will fail with MACH_RCV_INVALID_NAME. Instead, just + change the return value here to EINTR so mach_msg will not + retry and the EINTR error code will propagate up. */ + state->basic.SYSRETURN = EINTR; + *state_change = 1; + } + else if (reply) + rcv_port = *reply; + + /* All threads whose RPCs were interrupted by the interrupt_operation + call above will retry their RPCs unless we clear SS->intr_port. + So we clear it for the thread taking a signal when SA_RESTART is + clear, so that its call returns EINTR. */ + if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART)) + ss->intr_port = MACH_PORT_NULL; + } - return MACH_PORT_NULL; + return rcv_port; } + /* Abort the RPCs being run by all threads but this one; all other threads should be suspended. If LIVE is nonzero, those threads may run again, so they should be adjusted as necessary to be @@ -387,8 +389,9 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live) /* Abort any operation in progress with interrupt_operation. Record the reply port the thread is waiting on. We will wait for all the replies below. */ - reply_ports[nthreads++] = abort_rpcs (ss, signo, state, &state_changed, - NULL, 0, 0); + reply_ports[nthreads++] = _hurdsig_abort_rpcs (ss, signo, 1, + state, &state_changed, + NULL, 0, 0); if (state_changed && live) /* Aborting the RPC needed to change this thread's state, and it might ever run again. So write back its state. */ @@ -403,11 +406,18 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live) { error_t err; mach_msg_header_t head; - err = __mach_msg (&head, MACH_RCV_MSG, 0, sizeof head, + err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head, reply_ports[nthreads], - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (err != MACH_RCV_TOO_LARGE) - assert_perror (err); + _hurd_interrupted_rpc_timeout, MACH_PORT_NULL); + switch (err) + { + case MACH_RCV_TIMED_OUT: + case MACH_RCV_TOO_LARGE: + break; + + default: + assert_perror (err); + } } } @@ -745,7 +755,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss, if (! machine_get_basic_state (ss->thread, &thread_state)) goto sigbomb; - loc = interrupted_reply_port_location (&thread_state); + loc = interrupted_reply_port_location (&thread_state, 1); if (loc && *loc != MACH_PORT_NULL) /* This is the reply port for the context which called sigreturn. Since we are abandoning that context entirely @@ -759,11 +769,11 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss, } else { - wait_for_reply = (abort_rpcs (ss, signo, - &thread_state, &state_changed, - &reply_port, reply_port_type, - untraced) - != MACH_PORT_NULL); + wait_for_reply + = (_hurdsig_abort_rpcs (ss, signo, 1, + &thread_state, &state_changed, + &reply_port, reply_port_type, untraced) + != MACH_PORT_NULL); if (ss->critical_section) { @@ -790,7 +800,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss, { /* Fetch the thread variable for the MiG reply port, and set it to MACH_PORT_NULL. */ - mach_port_t *loc = interrupted_reply_port_location (&thread_state); + mach_port_t *loc = interrupted_reply_port_location (&thread_state, + 1); if (loc) { scp->sc_reply_port = *loc; diff --git a/hurd/intr-msg.c b/hurd/intr-msg.c new file mode 100644 index 0000000000..cdcd8d51ea --- /dev/null +++ b/hurd/intr-msg.c @@ -0,0 +1,151 @@ +/* Replacement for mach_msg used in interruptible Hurd RPCs. +Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <mach.h> +#include <mach/mig_errors.h> +#include <hurd/signal.h> + +error_t +_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t timeout, + mach_port_t notify) +{ + struct hurd_sigstate *ss = _hurd_self_sigstate (); + error_t err; + + /* Tell the signal thread that we are doing an interruptible RPC on + this port. If we get a signal and should return EINTR, the signal + thread will set this variable to MACH_PORT_NULL. The RPC might + return EINTR when some other thread gets a signal, in which case we + want to restart our call. */ + ss->intr_port = msg->msgh_remote_port; + + /* A signal may arrive here, after intr_port is set, but before + the mach_msg system call. The signal handler might do an + interruptible RPC, and clobber intr_port; then it would not be + set properly when we actually did send the RPC, and a later + signal wouldn't interrupt that RPC. So, + _hurd_setup_sighandler saves intr_port in the sigcontext, and + sigreturn restores it. */ + + message: + + if (ss->cancel) + { + err = EINTR; + ss->cancel = 0; + } + else + /* err = intr_msg_trap (msg, option, send_size, + rcv_size, rcv_name, timeout, notify); + */ + asm (".globl _hurd_intr_rpc_msg_do_trap\n" + ".globl _hurd_intr_rpc_msg_in_trap\n" + " movl %%esp, %%ecx\n" + " leal %1, %%esp\n" + " movl $-25, %%eax\n" + "_hurd_intr_rpc_msg_do_trap: lcall $7, $0 # status in %0\n" + "_hurd_intr_rpc_msg_in_trap: movl %%ecx, %%esp" + : "=a" (err) : "m" ((&msg)[1]) : "%ecx"); + + switch (err) + { + case MACH_SEND_INTERRUPTED: /* RPC didn't get out. */ + if (ss->intr_port != MACH_PORT_NULL) + /* If this signal was for us and it should interrupt calls, the + signal thread will have cleared SS->intr_port. + Since it's not cleared, the signal was for another thread, + or SA_RESTART is set. Restart the interrupted call. */ + goto message; + /* FALLTHROUGH */ + + case MACH_RCV_PORT_DIED: + /* Server didn't respond to interrupt_operation, + so the signal thread destroyed the reply port. */ + /* FALLTHROUGH */ + + case MACH_RCV_TIMED_OUT: + /* The operation was supposedly interrupted, but still has + not returned. Declare it interrupted. */ + + err = EINTR; + + /* The EINTR return indicates cancellation, so clear the flag. */ + ss->cancel = 0; + break; + + case MACH_RCV_INTERRUPTED: /* RPC sent; no reply. */ + option &= ~MACH_SEND_MSG; /* Don't send again. */ + if (ss->intr_port == MACH_PORT_NULL) + { + /* This signal or cancellation was for us. We need to wait for + the reply, but not hang forever. */ + option |= MACH_RCV_TIMEOUT; + timeout = _hurd_interrupted_rpc_timeout; + } + goto message; /* Retry the receive. */ + + case MACH_MSG_SUCCESS: + if (option & MACH_RCV_MSG) + { + /* We got a reply. Was it EINTR? */ + mig_reply_header_t *const reply = (void *) msg; + const union + { + mach_msg_type_t t; + int i; + } check = + { t: { + MACH_MSG_TYPE_INTEGER_32, + 32, + 1, + TRUE, + FALSE, + FALSE, + 0 + } }; + if (msg->msgh_size == sizeof *reply && + !(msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) && + *(int *) &reply->RetCodeType == check.i && + reply->RetCode == EINTR) + { + /* It is indeed EINTR. Is the interrupt for us? */ + if (ss->intr_port != MACH_PORT_NULL) + /* Nope; repeat the RPC. + XXX Resources moved? */ + goto message; + else + /* The EINTR return indicates cancellation, so clear the + flag. */ + ss->cancel = 0; + } + } + break; + + default: /* Quiet -Wswitch-enum. */ + } + + ss->intr_port = MACH_PORT_NULL; + + return err; +} diff --git a/hurd/intr-rpc.defs b/hurd/intr-rpc.defs index a2e7b060c9..7ed12bee62 100644 --- a/hurd/intr-rpc.defs +++ b/hurd/intr-rpc.defs @@ -1,5 +1,5 @@ /* Special MiG definitions for interruptible RPC stubs. -Copyright (C) 1994 Free Software Foundation, Inc. +Copyright (C) 1994, 1995 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,11 +17,7 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* Set the MiG options for an interruptible RPC interface. - We rename each MiG-generated function to hurd_intr_rpc_CALL and - give it the option to return on an interrupted message send. */ - -#define INTR_INTERFACE \ -msgoption MACH_SEND_INTERRUPT;\ -userprefix hurd_intr_rpc_; +/* Cause user stubs for interruptible RPCs to import a special header to + modify their behavior. */ +#define INTR_INTERFACE uimport "intr-rpc.h"; diff --git a/hurd/intr-rpc.h b/hurd/intr-rpc.h new file mode 100644 index 0000000000..169d1c7430 --- /dev/null +++ b/hurd/intr-rpc.h @@ -0,0 +1,25 @@ +/* Special MiG definitions for interruptible RPC stubs. +Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file is imported by the MiG-generated user stubs for interruptible + RPCs. We modify them to use our own function in place of mach_msg. */ + +#include <hurd/signal.h> + +#define __mach_msg _hurd_intr_rpc_mach_msg diff --git a/hurd/thread-cancel.c b/hurd/thread-cancel.c new file mode 100644 index 0000000000..db527c3935 --- /dev/null +++ b/hurd/thread-cancel.c @@ -0,0 +1,86 @@ +/* Thread cancellation support. +Copyright (C) 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <hurd/signal.h> +#include <hurd/interrupt.h> +#include <assert.h> +#include <thread_state.h> + + +/* See hurdsig.c. */ +extern mach_port_t _hurdsig_abort_rpcs (struct hurd_sigstate *ss, + int signo, int sigthread, + struct machine_thread_all_state *, + int *state_change, + mach_port_t *reply_port, + mach_msg_type_name_t reply_port_type, + int untraced); + +error_t +hurd_thread_cancel (thread_t thread) +{ + struct hurd_sigstate *ss = _hurd_thread_sigstate (thread); + struct machine_thread_all_state state; + int state_change; + error_t err; + + if (! ss) + return EINVAL; + + __spin_lock (&ss->lock); + assert (! ss->critical_section); + ss->critical_section = 1; + err = __thread_suspend (thread); + __spin_unlock (&ss->lock); + + if (! err) + { + /* Set the flag telling the thread its operation is being cancelled. */ + ss->cancel = 1; + + /* Interrupt any interruptible RPC now in progress. */ + state.set = 0; + _hurdsig_abort_rpcs (ss, 0, 0, &state, &state_change, NULL, 0, 0); + if (state_change) + err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state.basic, + MACHINE_THREAD_STATE_COUNT); + + __thread_resume (thread); + } + + _hurd_critical_section_unlock (ss); + return err; +} + + +int +hurd_check_cancel (void) +{ + struct hurd_sigstate *ss = _hurd_self_sigstate (); + int cancel; + + __spin_lock (&ss->lock); + assert (! ss->critical_section); + cancel = ss->cancel; + ss->cancel = 0; + __spin_unlock (&ss->lock); + + return cancel; +} diff --git a/libc-symbols.h b/libc-symbols.h index 951ea61ec2..7cc67a2b7e 100644 --- a/libc-symbols.h +++ b/libc-symbols.h @@ -141,15 +141,15 @@ Cambridge, MA 02139, USA. */ are better clued in to what we are doing. */ #undef strong_alias #define strong_alias(name, aliasname) \ - __typeof (name) aliasname __attribute__ ((alias (#name))); + extern __typeof (name) aliasname __attribute__ ((alias (#name))); #ifdef HAVE_WEAK_SYMBOLS #undef weak_symbol #define weak_symbol(name) \ - __typeof (name) name __attribute__ ((weak)); + extern __typeof (name) name __attribute__ ((weak)); #undef weak_alias #define weak_alias(name, aliasname) \ - __typeof (name) aliasname __attribute__ ((weak, alias (#name))); + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); #endif /* HAVE_WEAK_SYMBOLS. */ #endif /* Not ASSEMBLER, and GCC 2.7 or later. */ diff --git a/sysdeps/generic/morecore.c b/sysdeps/generic/morecore.c index 7c83e4aae5..a712eb310f 100644 --- a/sysdeps/generic/morecore.c +++ b/sysdeps/generic/morecore.c @@ -27,7 +27,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef __GNU_LIBRARY__ /* It is best not to declare this and cast its result on foreign operating systems with potentially hostile include files. */ -extern __ptr_t __sbrk __P ((int increment)); + +#include <stddef.h> +extern __ptr_t __sbrk __P ((ptrdiff_t increment)); #endif #ifndef NULL diff --git a/sysdeps/mach/hurd/alpha/trampoline.c b/sysdeps/mach/hurd/alpha/trampoline.c index 85f4964e14..f3872fcfe6 100644 --- a/sysdeps/mach/hurd/alpha/trampoline.c +++ b/sysdeps/mach/hurd/alpha/trampoline.c @@ -1,5 +1,5 @@ /* Set thread_state for sighandler, and sigcontext to recover. Alpha version. -Copyright (C) 1994 Free Software Foundation, Inc. +Copyright (C) 1994, 1995 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -160,6 +160,12 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, calls we retry need only wait to receive the reply message. */ args->option &= ~MACH_SEND_MSG; + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + state->basic.pc = (long int) &&rpc_wait_trampoline; /* After doing the message receive, the trampoline code will need to update the v0 ($0) value to be restored by sigreturn. To simplify @@ -245,42 +251,3 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, /* NOTREACHED */ return NULL; } - -/* STATE describes a thread that had intr_port set (meaning it was inside - HURD_EINTR_RPC), after it has been thread_abort'd. If it looks to have - just completed a mach_msg_trap system call that returned - MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right - being waited on. */ -int -_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, - mach_port_t *port) -{ - if (state->basic.r0 == MACH_RCV_INTERRUPTED) - { - const unsigned int *pc = (void *) state->basic.pc; - struct mach_msg_trap_args *args = (void *) &state->basic.r16; - - if (_hurdsig_catch_fault (SIGSEGV)) - { - assert (_hurdsig_fault_sigcode == (long int) (pc - 1) || - _hurdsig_fault_sigcode == (long int) &args->rcv_name); - /* We got a fault trying to read the PC or stack. */ - return 0; - } - else - { - if (pc[-1] == ((alpha_instruction) { pal_format: - { opcode: op_pal, - function: op_chmk } }).bits) - { - /* We did just return from a mach_msg_trap system call - doing a message receive that was interrupted. - Examine the parameters to find the receive right. */ - *port = args->rcv_name; - return 1; - } - } - } - - return 0; -} diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c index 8f303bf6bb..e55a615287 100644 --- a/sysdeps/mach/hurd/dl-sysdep.c +++ b/sysdeps/mach/hurd/dl-sysdep.c @@ -125,6 +125,7 @@ fmh(); /* XXX */ _hurd_startup (start_argptr, &go); LOSE; + abort (); } int @@ -137,7 +138,6 @@ _dl_sysdep_open_zero_fill (void) void _dl_sysdep_fatal (const char *msg, ...) { - extern __typeof (__io_write) __hurd_intr_rpc_io_write; va_list ap; va_start (ap, msg); @@ -147,8 +147,7 @@ _dl_sysdep_fatal (const char *msg, ...) mach_msg_type_number_t nwrote; do { - if (__hurd_intr_rpc_io_write (_hurd_init_dtable[2], - msg, len, -1, &nwrote)) + if (__io_write (_hurd_init_dtable[2], msg, len, -1, &nwrote)) break; len -= nwrote; msg += nwrote; @@ -169,8 +168,6 @@ _dl_sysdep_fatal (const char *msg, ...) int open (const char *file_name, int mode, ...) { - extern __typeof (__dir_lookup) __hurd_intr_rpc_dir_lookup; - extern __typeof (__io_reauthenticate) __hurd_intr_rpc_io_reauthenticate; enum retry_type doretry; char retryname[1024]; /* XXX string_t LOSES! */ file_t startdir, newpt, fileport; @@ -187,7 +184,7 @@ open (const char *file_name, int mode, ...) while (file_name[0] == '/') file_name++; - if (errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0, + if (errno = __dir_lookup (startdir, file_name, mode, 0, &doretry, retryname, &fileport)) return -1; @@ -207,7 +204,7 @@ open (const char *file_name, int mode, ...) case FS_RETRY_REAUTH: { mach_port_t ref = __mach_reply_port (); - errno = __hurd_intr_rpc_io_reauthenticate + errno = __io_reauthenticate (fileport, ref, MACH_MSG_TYPE_MAKE_SEND); if (! errno) errno = __auth_user_authenticate @@ -236,14 +233,12 @@ open (const char *file_name, int mode, ...) if (retryname[0] == '\0') { mach_port_t memobj_rd, memobj_wr; - extern __typeof (__io_map) __hurd_intr_rpc_io_map; dealloc_dir = 1; opened: /* We have the file open. Now map it. */ - errno = __hurd_intr_rpc_io_map (fileport, - &memobj_rd, &memobj_wr); + errno = __io_map (fileport, &memobj_rd, &memobj_wr); if (dealloc_dir) __mach_port_deallocate (__mach_task_self (), fileport); if (errno) @@ -359,7 +354,7 @@ open (const char *file_name, int mode, ...) if (! err) { mach_port_t ref = __mach_reply_port (); - err = __hurd_intr_rpc_io_reauthenticate + err = __io_reauthenticate (unauth, ref, MACH_MSG_TYPE_MAKE_SEND); if (! err) err = __auth_user_authenticate @@ -404,8 +399,8 @@ open (const char *file_name, int mode, ...) return -1; } - errno = __hurd_intr_rpc_dir_lookup (startdir, file_name, mode, 0, - &doretry, retryname, &fileport); + errno = __dir_lookup (startdir, file_name, mode, 0, + &doretry, retryname, &fileport); } } @@ -445,9 +440,8 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset) void _exit (int status) { - extern __typeof (__proc_mark_exit) __hurd_intr_rpc_proc_mark_exit; - __hurd_intr_rpc_proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC], - W_EXITCODE (status, 0)); + __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC], + W_EXITCODE (status, 0)); while (__task_terminate (__mach_task_self ())) __mach_task_self_ = (__mach_task_self) (); } @@ -513,11 +507,21 @@ longjmp (jmp_buf env, int val) { __longjmp (env[0].__jmpbuf, val); } weak_symbol (longjmp) -/* Stub out this function that is called by interruptible RPC stubs. It - should never get called during initial dynamic linking, because we use - only the raw MiG stub functions __hurd_intr_rpc_*. Since this defn is +/* This function is called by interruptible RPC stubs. For initial + dynamic linking, just use the normal mach_msg. Since this defn is weak, the real defn in libc.so will override it if we are linked into the user program (-ldl). */ -struct hurd_sigstate * -_hurd_thread_sigstate (thread_t thread) { thread = thread; abort (); } -weak_symbol (_hurd_thread_sigstate) + +error_t +_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t timeout, + mach_port_t notify) +{ + return __mach_msg (msg, option, send_size, rcv_size, rcv_name, + timeout, notify); +} +weak_symbol (_hurd_intr_rpc_mach_msg) diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c index 8e625b8e5e..b8b15743cd 100644 --- a/sysdeps/mach/hurd/fork.c +++ b/sysdeps/mach/hurd/fork.c @@ -27,9 +27,6 @@ Cambridge, MA 02139, USA. */ #include <assert.h> #include "hurdmalloc.h" /* XXX */ -extern void _hurd_longjmp_thread_state (struct machine_thread_state *, - jmp_buf env, int value); - /* Things that want to be locked while forking. */ struct diff --git a/sysdeps/mach/hurd/hppa/trampoline.c b/sysdeps/mach/hurd/hppa/trampoline.c index 09ab71e88d..1dbbe6dead 100644 --- a/sysdeps/mach/hurd/hppa/trampoline.c +++ b/sysdeps/mach/hurd/hppa/trampoline.c @@ -144,6 +144,12 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, calls we retry need only wait to receive the reply message. */ args->option &= ~MACH_SEND_MSG; + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + _hurdsig_end_catch_fault (); MACHINE_THREAD_STATE_SET_PC (&state->basic, &&rpc_wait_trampoline); @@ -222,37 +228,3 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, /* NOTREACHED */ return NULL; } - -/* STATE describes a thread that had intr_port set (meaning it was inside - HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have - just completed a mach_msg_trap system call that returned - MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right - being waited on. */ -int -_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, - mach_port_t *port) -{ - const unsigned int *volatile pc - = MACHINE_THREAD_STATE_PC (&state->basic); - const mach_port_t *rcv_name - = (void *) state->r30 -32-20; /* VA_ARG4 from <mach/machine/asm.h>. */ - - if (_hurdsig_catch_fault (SIGSEGV)) - assert (_hurdsig_fault_sigcode == (long int) pc || - _hurdsig_fault_sigcode == (long int) rcv_name); - else - { - int rcving = (state->basic.r28 == MACH_RCV_INTERRUPTED && - pc == ???unfinished???); - if (rcving) - /* We did just return from a mach_msg_trap system call - doing a message receive that was interrupted. - Examine the parameters to find the receive right. */ - *port = *rcv_name; - _hurdsig_end_catch_fault (); - if (rcving) - return 1; - } - - return 0; -} diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c index 2a31588e21..7adffc40be 100644 --- a/sysdeps/mach/hurd/i386/trampoline.c +++ b/sysdeps/mach/hurd/i386/trampoline.c @@ -181,6 +181,12 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, calls we retry need only wait to receive the reply message. */ args->option &= ~MACH_SEND_MSG; + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + _hurdsig_end_catch_fault (); state->basic.eip = (int) &&rpc_wait_trampoline; @@ -250,39 +256,3 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, /* NOTREACHED */ return NULL; } - -/* STATE describes a thread that had intr_port set (meaning it was inside - HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have - just completed a mach_msg_trap system call that returned - MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right - being waited on. */ -int -_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, - mach_port_t *port) -{ - static const unsigned char syscall[] = { 0x9a, 0, 0, 0, 0, 7, 0 }; - const unsigned char *volatile pc - = (void *) state->basic.eip - sizeof syscall; - - if (_hurdsig_catch_fault (SIGSEGV)) - assert (_hurdsig_fault_sigcode >= (long int) pc && - _hurdsig_fault_sigcode < (long int) (pc + sizeof syscall)); - else - { - int rcving = (state->basic.eax == MACH_RCV_INTERRUPTED && - !memcmp (pc, &syscall, sizeof syscall)); - _hurdsig_end_catch_fault (); - if (rcving) - { - /* We did just return from a mach_msg_trap system call - doing a message receive that was interrupted. - Examine the parameters to find the receive right. */ - struct mach_msg_trap_args *args = (void *) state->basic.uesp; - - *port = args->rcv_name; - return 1; - } - } - - return 0; -} diff --git a/sysdeps/mach/hurd/ioctl.c b/sysdeps/mach/hurd/ioctl.c index 4aad0bb377..a1523c6c4d 100644 --- a/sysdeps/mach/hurd/ioctl.c +++ b/sysdeps/mach/hurd/ioctl.c @@ -79,11 +79,11 @@ DEFUN(__ioctl, (fd, request), m->msgh_id = msgid; m->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); - err = HURD_EINTR_RPC (ioport, __mach_msg (m, MACH_SEND_MSG|MACH_RCV_MSG, - m->msgh_size, sizeof (msg), - m->msgh_local_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL)); + err = _hurd_intr_rpc_mach_msg (m, MACH_SEND_MSG|MACH_RCV_MSG, + m->msgh_size, sizeof (msg), + m->msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); switch (err) { case MACH_MSG_SUCCESS: diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c index a6abdc5a47..bedc13760c 100644 --- a/sysdeps/mach/hurd/kill.c +++ b/sysdeps/mach/hurd/kill.c @@ -37,8 +37,6 @@ __kill (pid_t pid, int sig) inline void kill_pid (pid_t pid) /* Kill one PID. */ { - - /* SIGKILL is not delivered as a normal signal. Sending SIGKILL to a process means to terminate its task. */ if (sig == SIGKILL) diff --git a/sysdeps/mach/hurd/mips/trampoline.c b/sysdeps/mach/hurd/mips/trampoline.c index f03ad5852f..03e3d1da6f 100644 --- a/sysdeps/mach/hurd/mips/trampoline.c +++ b/sysdeps/mach/hurd/mips/trampoline.c @@ -150,6 +150,12 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, calls we retry need only wait to receive the reply message. */ args->option &= ~MACH_SEND_MSG; + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + state->basic.pc = (int) &&rpc_wait_trampoline; state->basic.r29 = (int) sigsp; /* $29 is the stack pointer register. */ /* After doing the message receive, the trampoline code will need to @@ -227,34 +233,3 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, return NULL; } - -/* STATE describes a thread that had intr_port set (meaning it was inside - HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have - just completed a mach_msg_trap system call that returned - MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right - being waited on. */ -int -_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, - mach_port_t *port) -{ - const unsigned int *const pc = (void *) state->basic.pc; - - if (_hurdsig_catch_fault (SIGSEGV)) - assert (_hurdsig_fault_sigcode == (long int) pc); - else - { - if (state->basic.r2 == MACH_RCV_INTERRUPTED && - pc[-1] == 0xc) /* syscall */ - { - /* We did just return from a mach_msg_trap system call - doing a message receive that was interrupted. - Examine the parameters to find the receive right. */ - struct mach_msg_trap_args *args = (void *) &state->basic.r4; - - *port = args->rcv_name; - return 1; - } - } - - return 0; -} |