]> sourceware.org Git - glibc.git/commitdiff
Mon Aug 14 16:51:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
authorRoland McGrath <roland@gnu.org>
Mon, 14 Aug 1995 22:49:23 +0000 (22:49 +0000)
committerRoland McGrath <roland@gnu.org>
Mon, 14 Aug 1995 22:49:23 +0000 (22:49 +0000)
* 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.

19 files changed:
ChangeLog
hurd/Makefile
hurd/hurd.h
hurd/hurd/signal.h
hurd/hurdsig.c
hurd/intr-msg.c [new file with mode: 0644]
hurd/intr-rpc.defs
hurd/intr-rpc.h [new file with mode: 0644]
hurd/thread-cancel.c [new file with mode: 0644]
libc-symbols.h
sysdeps/generic/morecore.c
sysdeps/mach/hurd/alpha/trampoline.c
sysdeps/mach/hurd/dl-sysdep.c
sysdeps/mach/hurd/fork.c
sysdeps/mach/hurd/hppa/trampoline.c
sysdeps/mach/hurd/i386/trampoline.c
sysdeps/mach/hurd/ioctl.c
sysdeps/mach/hurd/kill.c
sysdeps/mach/hurd/mips/trampoline.c

index c204666b0c613411f86a61a858404c6bd251f80a..ff8389bfd8166ba706e199c84e7b21fa16fb0ef9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 5e1622d87deb0cb0ecf5bd766daaf9c28099d40d..58bea5f1c0f8154c833d5440198cee8e4625fc09 100644 (file)
@@ -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
 \f
 # 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) \
index e0ba62eedeb6119701303c20e973c1949de54cea..1b4db17efeaaf63e414a4205b3a21046b25bd793 100644 (file)
@@ -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.  */
index d28d1c6c11eb3481f47af6671e596e9c4719af53..a032313e4ec26e68e7debb5b35d051b6cadbd99b 100644 (file)
@@ -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.  */
index 9414c059e351ecdfef79c39e71f21e31152d13f2..7dd2b8c2fcff6b91a2e3ca0441b60375a6c9e6fd 100644 (file)
@@ -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;
 \f
 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 (file)
index 0000000..cdcd8d5
--- /dev/null
@@ -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;
+}
index a2e7b060c97f8a9dfb1c2309f9a49a53c7ebc888..7ed12bee6230e552540591415b5ced3d08cd0112 100644 (file)
@@ -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 (file)
index 0000000..169d1c7
--- /dev/null
@@ -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 (file)
index 0000000..db527c3
--- /dev/null
@@ -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;
+}
index 951ea61ec271bdbf460439882f0ce5ea8ae1f4dd..7cc67a2b7e50b142203cba10a60adbf9e09438d3 100644 (file)
@@ -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.  */
 
index 7c83e4aae56856da5c95763cd6ea190d74bdd0bc..a712eb310f0948ba4c785c4ed2aaec181c27f4e2 100644 (file)
@@ -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
index 85f4964e14f5892993659ad6f8bfa2d0d092c60e..f3872fcfe6351035308be0676a179c4693634efd 100644 (file)
@@ -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;
 }
-\f
-/* 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;
-}
index 8f303bf6bb6e1d54dbf8eff48b6ac61289a8584a..e55a6152870d2adac5f4bd10cff98798868b29ef 100644 (file)
@@ -125,6 +125,7 @@ fmh();                              /* XXX */
   _hurd_startup (start_argptr, &go);
 
   LOSE;
+  abort ();
 }
 \f
 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)
index 8e625b8e5e8043acf88e04cda79e75326b08c9a9..b8b15743cd8ded8540dfdbb8c0ff76853981c9ac 100644 (file)
@@ -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
index 09ab71e88dfa66a7b7fe45b0a28d6eddebbbe921..1dbbe6deadc6c1cf585a3c4932e5ab50929f230a 100644 (file)
@@ -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;
 }
-\f
-/* 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;
-}
index 2a31588e21836b75e5ee301d5b388ad10208501d..7adffc40be58f258da4285e56038844efdcb07c0 100644 (file)
@@ -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;
 }
-\f
-/* 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;
-}
index 4aad0bb377c0a17eadc2fd4b4f6945ccbd224c1a..a1523c6c4d5d3e4131f3aac54b2fb7791486f557 100644 (file)
@@ -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:
index a6abdc5a477c8503ad61fe9a05421eff0e8d0e86..bedc13760c31378972a41467f12cc423a0443042 100644 (file)
@@ -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)
index f03ad5852ff6f7f9f3b0f8839ffc2f1f0a4ee13c..03e3d1da6fc9b50251247daaa9e1268eb778d73d 100644 (file)
@@ -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;
 }
-\f
-/* 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;
-}
This page took 0.081098 seconds and 5 git commands to generate.