summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2013-12-10 15:31:36 +0100
committerJustus Winter <4winter@informatik.uni-hamburg.de>2013-12-10 18:04:38 +0100
commit77ba38a61492799cc3c615f0f622f34fc10de826 (patch)
tree76b65c7c619564e3a458fce64c9f0a9afba89340
parent0bdd1a9d8d3eef8cae027be133ee11fc9a3b5165 (diff)
utils/settrans: fix the teardown of chrooted environments
Previously, settrans --chroot would just exec the target. Create a new process for that purpose. Wait for its completion, then ask the translator (nicely by default) to go away. If it refuses with EBUSY, it might be because some process has daemonized inside the chrooted environment. This fixes the following bug when settrans is used with fakeroot: % fakeroot-hurd /bin/true 2>&1 | tee <hangs> Here, fakeroot-hurd execs settrans with --chroot, settrans execs /hurd/fakeauth which will eventually exec the target /bin/true. When true terminates, it will close its stdout and stderr. But /hurd/fakeroot's stderr is also connected to tee's stdin, preventing tee from exiting. * utils/settrans.c (main): Fix the teardown of chrooted environments.
-rw-r--r--utils/settrans.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/utils/settrans.c b/utils/settrans.c
index d13e7c41..ecc6d753 100644
--- a/utils/settrans.c
+++ b/utils/settrans.c
@@ -25,6 +25,7 @@
#include <error.h>
#include <fcntl.h>
#include <unistd.h>
+#include <sys/wait.h>
#include <error.h>
#include <argz.h>
@@ -279,33 +280,51 @@ main(int argc, char *argv[])
if (chroot_command)
{
- /* We will act as the parent filesystem would for a lookup
- of the active translator's root node, then use this port
- as our root directory while we exec the command. */
-
- char retry_name[1024]; /* XXX */
- retry_type do_retry;
- mach_port_t root;
- err = fsys_getroot (active_control,
- MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
- NULL, 0, NULL, 0, 0, &do_retry, retry_name, &root);
- mach_port_deallocate (mach_task_self (), active_control);
- if (err)
- error (6, err, "fsys_getroot");
- err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
- do_retry, retry_name, 0, 0,
- &root);
- if (err)
- error (6, err, "cannot resolve root port");
+ pid_t pid;
+ switch ((pid = fork ()))
+ {
+ case -1:
+ error (6, errno, "fork");
+
+ case 0:; /* Child. */
+ /* We will act as the parent filesystem would for a lookup
+ of the active translator's root node, then use this port
+ as our root directory while we exec the command. */
+
+ char retry_name[1024]; /* XXX */
+ retry_type do_retry;
+ mach_port_t root;
+ err = fsys_getroot (active_control,
+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
+ NULL, 0, NULL, 0, 0,
+ &do_retry, retry_name, &root);
+ mach_port_deallocate (mach_task_self (), active_control);
+ if (err)
+ error (6, err, "fsys_getroot");
+ err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
+ do_retry, retry_name, 0, 0,
+ &root);
+ if (err)
+ error (6, err, "cannot resolve root port");
+
+ if (setcrdir (root))
+ error (7, errno, "cannot install root port");
+ mach_port_deallocate (mach_task_self (), root);
+ if (chdir ("/"))
+ error (8, errno, "cannot chdir to new root");
+
+ execvp (chroot_command[0], chroot_command);
+ error (8, errno, "cannot execute %s", chroot_command[0]);
+ break;
- if (setcrdir (root))
- error (7, errno, "cannot install root port");
- mach_port_deallocate (mach_task_self (), root);
- if (chdir ("/"))
- error (8, errno, "cannot chdir to new root");
+ default: /* Parent. */
+ if (waitpid (pid, NULL, 0) == -1)
+ error (8, errno, "waitpid");
- execvp (chroot_command[0], chroot_command);
- error (8, errno, "cannot execute %s", chroot_command[0]);
+ err = fsys_goaway (active_control, goaway_flags);
+ if (err && err != EBUSY)
+ error (9, err, "fsys_goaway");
+ }
}
return 0;