Mike Kelly, le mar. 31 mars 2026 21:26:42 +0100, a ecrit:
> An interrupted RPC call can return EINTR whilst the RPC is still in
> progress on the server. Some RPC calls have permanent consequences
> (eg. a write() to append data to a file) but a caller seeing EINTR
> should expect that no state has changed. The signal thread now stores
> the server's reply (which it already waited for) as the interrupted
> thread's reply.

The principle looks good to me, just a catch here:

> ---
>  hurd/hurdsig.c | 67 +++++++++++++++++++++++++++++---------------------
>  1 file changed, 39 insertions(+), 28 deletions(-)
> 
> diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
> index cb3e04ec0d..79501bebc5 100644
> --- a/hurd/hurdsig.c
> +++ b/hurd/hurdsig.c
> @@ -547,24 +542,40 @@ abort_all_rpcs (int signo, struct 
> machine_thread_all_state *state, int live)
>         }
>        }
>  
> +  /* All threads (except this one) are suspended, so _hurd_sigstates
> +     cannot have changed and therefore indexes into reply_ports still
> +     match the _hurd_sigstates sequence. */
> +  nthreads = 0;
> +
>    /* Wait for replies from all the successfully interrupted RPCs.  */
> -  while (nthreads-- > 0)
> +  for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, nthreads += 1)
>      if (reply_ports[nthreads] != MACH_PORT_NULL)
>        {
> +     machine_get_basic_state (ss->thread, state);
> +
> +     /* We use the message header/rcv_size supplied to the thread
> +        that initiated the RPC so that the reply is available to it
> +        if it resumes. */
>       error_t err;
> -     mach_msg_header_t head;
> -     err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
> +     mach_msg_header_t *head = (mach_msg_header_t *) state->basic.rdi;
> +     mach_msg_size_t rcv_size = (mach_msg_size_t) state->basic.r10;

This needs to be made arch-dependent by adding ARG macros along
SYSRETURN in thread_state.h

> +
> +     assert (head != NULL && rcv_size >= sizeof(mach_msg_header_t));
> +
> +     err = __mach_msg (head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, rcv_size,
>                         reply_ports[nthreads],
>                         _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
> -     switch (err)
> +     if (live)
>         {
> -       case MACH_RCV_TIMED_OUT:
> -       case MACH_RCV_TOO_LARGE:
> -         break;
> -
> -       default:
> -         assert_perror (err);
> +         /* The RPC might have any result including success. The
> +            suspended thread must deal with the outcome. */
> +         state->basic.SYSRETURN = err;
> +         __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
> +                             (natural_t *) &state->basic,
> +                             MACHINE_THREAD_STATE_COUNT);
>         }
> +     else if (err != MACH_RCV_TIMED_OUT)
> +       assert_perror (err);
>        }
>  }
>  
> -- 
> 2.47.3
> 
> 
Samuel

Reply via email to