summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2022-08-23 04:25:54 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-08-23 04:25:54 +0200
commit772e292c2d47e9d93455e3c87ae0209a58a3da67 (patch)
treeb75ed8330d15e3f1937c057b4573c4482e0db31c
parentcb372e4d5ae9db30aef20150f1242392459ed808 (diff)
Fix spurious EINTR while exec() within fakeroot
The scenario is: - process running inside fakeroot exec()s - fakeroot forwards the exec call - exec starts thrashing the previous process, and notably close its ports - the send port that pointed to fakeroot is thus closed - fakeroot thus receives a no-senders notification - its libports thus interrupts the current RPC on it, i.e. the exec(), because it thinks that the caller is no more, but that was exactly the point of the exec()... - exec tries to interrupt its own RPCs, at best the execution will fail, at worse the process is already thrashed and there's nothing better than burying it for good. The symptom is processes running inside fakeroot seeming randomly crashing with SIGKILL. Making fakeroot keep a send right avoids the no-senders notification, thus the whole interruption (which was meaningless).
-rw-r--r--trans/fakeroot.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/trans/fakeroot.c b/trans/fakeroot.c
index 944fafdb..e70cb280 100644
--- a/trans/fakeroot.c
+++ b/trans/fakeroot.c
@@ -939,6 +939,11 @@ netfs_S_file_exec_paths (struct protid *user,
file, MACH_PORT_RIGHT_SEND, 1);
pthread_mutex_unlock (&user->po->np->lock);
+ /* Add a gratuitous send right on the protid to avoid a no-sender, and thus
+ interrupt the exec, just because we are precisely replacing the calling
+ process! */
+ mach_port_t gratuitous = ports_get_send_right (user);
+
if (!err)
{
#ifdef HAVE_FILE_EXEC_PATHS
@@ -977,6 +982,9 @@ netfs_S_file_exec_paths (struct protid *user,
for (i = 0; i < portarraylen; ++i)
mach_port_deallocate (mach_task_self (), portarray[i]);
}
+
+ mach_port_deallocate (mach_task_self (), gratuitous);
+
return err;
}