aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>1998-03-27 06:14:10 +0000
committerH. Peter Anvin <hpa@zytor.com>1998-03-27 06:14:10 +0000
commitf5888e2e45e3170f0003fee359f35f839ba468ea (patch)
treeb14e0f5e838919129047e525df21086450e3a6cc
parentc8c6aec4a542e41b899bd1f89ef335b3f5b53aff (diff)
downloadautofs3-f5888e2e45e3170f0003fee359f35f839ba468ea.tar.gz
autofs3-f5888e2e45e3170f0003fee359f35f839ba468ea.tar.xz
autofs3-f5888e2e45e3170f0003fee359f35f839ba468ea.zip
Change submount synchronization to not detach (we'll get detached when
the parent process exits); use signals for proper synchronization.
-rw-r--r--daemon/automount.c26
-rw-r--r--modules/mount_autofs.c57
2 files changed, 36 insertions, 47 deletions
diff --git a/daemon/automount.c b/daemon/automount.c
index a7f9582..f51b8dc 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -501,32 +501,29 @@ static void become_daemon(void)
int nullfd;
/* Don't BUSY any directories unneccessarily */
-
chdir("/");
/* Detach from foreground process */
-
- pid = fork();
- if ( pid > 0 )
- exit(0);
- else if ( pid < 0 ) {
- fprintf(stderr, "%s: Could not detach process\n", program);
- exit(1);
+ if ( !submount ) {
+ pid = fork();
+ if ( pid > 0 )
+ exit(0);
+ else if ( pid < 0 ) {
+ fprintf(stderr, "%s: Could not detach process\n", program);
+ exit(1);
+ }
}
/* Open syslog */
-
openlog("automount", LOG_PID, LOG_DAEMON);
/* Initialize global data */
-
my_pid = getpid();
/* Make our own process group for "magic" reason: processes that share
our pgrp see the raw filesystem behine the magic. So if we are a
submount, don't change -- otherwise we won't be able to actually
perform the mount. */
-
if ( !submount && setpgrp() ) {
syslog(LOG_CRIT, "setpgrp: %m");
exit(1);
@@ -534,7 +531,6 @@ static void become_daemon(void)
my_pgrp = getpgrp();
/* Redirect all our file descriptors to /dev/null */
-
if ( (nullfd = open("/dev/null", O_RDWR)) < 0 ) {
syslog(LOG_CRIT, "cannot open /dev/null: %m");
exit(1);
@@ -549,7 +545,6 @@ static void become_daemon(void)
close(nullfd);
/* Write pid file if requested */
-
if ( pid_file ) {
if ( (pidfp = fopen(pid_file, "wt")) ) {
fprintf(pidfp, "%lu\n", (unsigned long) my_pid);
@@ -784,6 +779,11 @@ int main(int argc, char *argv[])
if ( ap.exp_timeout )
alarm(ap.exp_timeout + my_pid % ap.exp_runfreq);
}
+
+ /* Initialization successful. If we're a submount, send outself SIGSTOP to let
+ our parent know that we have grown up and don't need supervision anymore. */
+ if ( submount )
+ kill(my_pid, SIGSTOP);
while ( !shutdown ) {
if (handle_packet() && errno != EINTR)
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index 6ab439c..ed9f2e9 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -36,11 +36,10 @@ int mount_mount(const char *root, const char *name, int name_len,
const char *what, const char *fstype, const char *c_options,
void *context)
{
- char *fullpath;
- const char **argv;
+ char *fullpath, **argv;
int argc, status;
- struct stat sb, cb;
char *options, *p;
+ pid_t slave, wp;
fullpath = alloca(strlen(root)+name_len+2);
if ( !fullpath ) {
@@ -74,7 +73,7 @@ int mount_mount(const char *root, const char *name, int name_len,
argc++;
} while ((p = strchr(p,',')) != NULL);
}
- argv = (const char **) alloca((argc+1) * sizeof(char *));
+ argv = (char **) alloca((argc+1) * sizeof(char *));
argc = 0;
argv[argc++] = _PATH_AUTOMOUNT;
@@ -96,42 +95,32 @@ int mount_mount(const char *root, const char *name, int name_len,
}
argv[argc] = NULL;
- /* Spawn a new daemon. */
- status = spawnv(LOG_DEBUG, _PATH_AUTOMOUNT, argv);
- if (!WIFEXITED(status) || WEXITSTATUS(status)) {
- syslog(LOG_NOTICE, MODPREFIX "sub automount returned status %d", status);
+ /* Spawn a new daemon. If initialization is successful, the daemon will send
+ itself SIGSTOP, which we detect and let it go on its merry way. */
+
+ slave = fork();
+ if ( slave < 0 ) {
+ syslog(LOG_ERR, MODPREFIX "fork: %m");
goto error;
+ } else if ( slave == 0 ) {
+ /* Slave process */
+ execv(_PATH_AUTOMOUNT, argv);
+ _exit(255);
}
- /* We must wait a bit for it to get registered. We try three times, and
- if it isn't ready after that, assume it has failed. This is a real
- hack; we really should make --submount make the subprocess notify us. */
-
- stat(root, &cb);
- usleep(10000);
-
- stat(fullpath, &sb);
- if (cb.st_dev == sb.st_dev) {
- int i;
- /* First, to one second by tenths. */
- for (i = 0; i < 10; ++i) {
- usleep(100000);
- stat(fullpath, &sb);
- if (cb.st_dev != sb.st_dev)
- goto ok;
- }
- /* Then to one minute by seconds. */
- for (i = 1; i < 60; ++i) {
- sleep(1);
- stat(fullpath, &sb);
- if (cb.st_dev != sb.st_dev)
- goto ok;
- }
- syslog(LOG_NOTICE, MODPREFIX "timeout waiting for submount");
+ while ( (wp = waitpid(slave, &status, WUNTRACED)) == -1 && errno == EINTR );
+ if ( wp != slave ) {
+ syslog(LOG_NOTICE, MODPREFIX "waitpid: %m");
goto error;
}
-ok:
+ if ( !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP ) {
+ syslog(LOG_NOTICE, MODPREFIX "sub automount returned status 0x%x", status);
+ goto error;
+ }
+
+ kill(slave, SIGCONT); /* Carry on, private */
+
syslog(LOG_DEBUG, MODPREFIX "mounted %s on %s", what, fullpath);
return 0;