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