From bab11d536f278a5856c42b00fa87f8d5b8d29065 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 28 Feb 2025 20:06:42 +0100 Subject: pfinet: Fix spurious EINTR errors from select While sleeping in pthread_hurd_cond_timedwait_np, current->signal will be overwritten by the management of other RPCs, so we have to give it some value on wake up. Also, if we previously got interrupted, we shouldn't ever try to wait again until exiting from the RPC: an interrupt means we really want to try hard to finish the RPC. Thanks Zhaoming Luo for the deep investigation and draft! --- pfinet/glue-include/linux/sched.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'pfinet/glue-include/linux/sched.h') diff --git a/pfinet/glue-include/linux/sched.h b/pfinet/glue-include/linux/sched.h index b91c3edf..31cfecbb 100644 --- a/pfinet/glue-include/linux/sched.h +++ b/pfinet/glue-include/linux/sched.h @@ -113,9 +113,23 @@ interruptible_sleep_on_timeout (struct wait_queue **p, struct timespec *tsp) isroot = current->isroot; /* This is our context that needs switched. */ next_wait = current->next_wait; /* This too, for multiple schedule calls. */ current->next_wait = 0; - err = pthread_hurd_cond_timedwait_np(c, &global_lock, tsp); - if (err == EINTR) - current->signal = 1; /* We got cancelled, mark it for later. */ + + if (current->signal) + /* We already got interrupted previously, keep interrupting the + RPC. */ + err = EINTR; + else + { + /* This is the only place where we sleep within an RPC and release the global + lock while serving it. */ + err = pthread_hurd_cond_timedwait_np(c, &global_lock, tsp); + + if (err == EINTR) + current->signal = 1; /* We got cancelled, mark it for Linux code to bail out. */ + else + current->signal = 0; + } + current->isroot = isroot; /* Switch back to our context. */ current->next_wait = next_wait; return (err == ETIMEDOUT); -- cgit v1.2.3