summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2025-02-28 20:06:42 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2025-02-28 20:06:42 +0100
commitbab11d536f278a5856c42b00fa87f8d5b8d29065 (patch)
tree09dbb65a0f07b88f73d755914eb8b9abbb56d425
parent1d7bfa53e29b52afb43d02eed126a37374fa3be9 (diff)
pfinet: Fix spurious EINTR errors from selectv0.9.git20250304
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 <zhmingluo@163.com> for the deep investigation and draft!
-rw-r--r--pfinet/glue-include/linux/sched.h20
1 files changed, 17 insertions, 3 deletions
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);