(handler): removed this bad signal handler.
(lock_mtab): Redhat's original code set a signal handler called
"handler()" for all non-ALRM signals. The handler called
unlock_mntlist(), plog'ed the signal name, and then exit(1)!
Never, ever, exit() from inside a utility function. This messed
up Amd's careful signal-handling code, and caused Amd to abort
uncleanly only any other "innocent" signal
(even simple SIGUSR1), leaving behind a hung Amd mnt point. That
code should have at least restored the signal handlers' states
upon a successful mtab unlocking. Anyway, that handler was
unnecessary, because will call unlock_mntlist() properly anyway on
exit.
* conf/mtab/mtab_{file,isc3,mach3,linux}.c (unlock_mntlist): dlog
message that we're inside the unlock_mntlist function.
* amd/amd.c (main): use new setup_sighandler() for Amd's four main
signals (INT, TERM, HUP, and CHLD).
(main) Add SIGINT and SIGTERM to masked_sigs, used in
nfs_start.c:do_select() for setjmp/longjmp code; the MASK was set
to all four signals if !HAVE_SIGACTION, but only to HUP+CHLD if we
HAVE_SIGACTION. So this change makes Amd behave consistently.
* include/am_utils.h: extern for new setup_sighandler().
* libamu/xutil.c (setup_sighandler): new utility function to setup
a single signal-handler regardless of what method is supported by
this OS.
(going_down): call unlock_mntlist() when exiting, to ensure that
Amd will remove any leftover mtab lock files, if any.
* amd/restart.c (restart_automounter_nodes): cleanup function.
2005-08-01 Erez Zadok <ezk@cs.sunysb.edu>
+ * conf/mtab/mtab_linux.c: removed unused code. Cleanup.
+ (handler): removed this bad signal handler.
+ (lock_mtab): Redhat's original code set a signal handler called
+ "handler()" for all non-ALRM signals. The handler called
+ unlock_mntlist(), plog'ed the signal name, and then exit(1)!
+ Never, ever, exit() from inside a utility function. This messed
+ up Amd's careful signal-handling code, and caused Amd to abort
+ uncleanly only any other "innocent" signal
+ (even simple SIGUSR1), leaving behind a hung Amd mnt point. That
+ code should have at least restored the signal handlers' states
+ upon a successful mtab unlocking. Anyway, that handler was
+ unnecessary, because will call unlock_mntlist() properly anyway on
+ exit.
+
+ * conf/mtab/mtab_{file,isc3,mach3,linux}.c (unlock_mntlist): dlog
+ message that we're inside the unlock_mntlist function.
+
+ * amd/amd.c (main): use new setup_sighandler() for Amd's four main
+ signals (INT, TERM, HUP, and CHLD).
+ (main) Add SIGINT and SIGTERM to masked_sigs, used in
+ nfs_start.c:do_select() for setjmp/longjmp code; the MASK was set
+ to all four signals if !HAVE_SIGACTION, but only to HUP+CHLD if we
+ HAVE_SIGACTION. So this change makes Amd behave consistently.
+
+ * include/am_utils.h: extern for new setup_sighandler().
+
+ * libamu/xutil.c (setup_sighandler): new utility function to setup
+ a single signal-handler regardless of what method is supported by
+ this OS.
+ (going_down): call unlock_mntlist() when exiting, to ensure that
+ Amd will remove any leftover mtab lock files, if any.
+
+ * amd/restart.c (restart_automounter_nodes): cleanup function.
+
* minor new port: i386-pc-linuxoldld-deb3.1.
* configure.in: include <sys/types.h> before <linux/socket.h> to
* SUCH DAMAGE.
*
*
- * $Id: amd.c,v 1.36 2005/05/12 23:01:25 ottavio Exp $
+ * $Id: amd.c,v 1.37 2005/08/02 01:28:57 ezk Exp $
*
*/
int error;
char *progname = NULL; /* "amd" */
char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
-#ifdef HAVE_SIGACTION
- struct sigaction sa;
-#endif /* HAVE_SIGACTION */
/*
* Make sure some built-in assumptions are true before we start
am_set_hostname(hostname);
/*
- * Trap interrupts for shutdowns.
+ * Setup signal handlers
*/
-#ifdef HAVE_SIGACTION
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = sigterm;
- sa.sa_flags = 0;
- sigemptyset(&(sa.sa_mask));
- sigaddset(&(sa.sa_mask), SIGINT);
- sigaddset(&(sa.sa_mask), SIGTERM);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
-#else /* not HAVE_SIGACTION */
- (void) signal(SIGINT, sigterm);
-#endif /* not HAVE_SIGACTION */
-
+ /* SIGINT: trap interrupts for shutdowns */
+ setup_sighandler(SIGINT, sigterm);
+ /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
+ setup_sighandler(SIGTERM, sigterm);
+ /* SIGHUP: hangups tell us to reload the cache */
+ setup_sighandler(SIGHUP, sighup);
/*
- * Trap Terminate so that we can shutdown gracefully (some chance)
+ * SIGCHLD: trap Death-of-a-child. These allow us to pick up the exit
+ * status of backgrounded mounts. See "sched.c".
*/
+ setup_sighandler(SIGCHLD, sigchld);
#ifdef HAVE_SIGACTION
- sa.sa_handler = sigterm;
- sa.sa_flags = 0;
- sigemptyset(&(sa.sa_mask));
- sigaddset(&(sa.sa_mask), SIGTERM);
- sigaction(SIGTERM, &sa, NULL);
-#else /* not HAVE_SIGACTION */
- (void) signal(SIGTERM, sigterm);
-#endif /* not HAVE_SIGACTION */
-
- /*
- * Hangups tell us to reload the cache
- */
-#ifdef HAVE_SIGACTION
- sa.sa_handler = sighup;
- sa.sa_flags = 0;
- sigemptyset(&(sa.sa_mask));
- sigaddset(&(sa.sa_mask), SIGHUP);
- sigaction(SIGHUP, &sa, NULL);
-#else /* not HAVE_SIGACTION */
- (void) signal(SIGHUP, sighup);
-#endif /* not HAVE_SIGACTION */
-
- /*
- * Trap Death-of-a-child. These allow us to
- * pick up the exit status of backgrounded mounts.
- * See "sched.c".
- */
-#ifdef HAVE_SIGACTION
- sa.sa_handler = sigchld;
- sa.sa_flags = 0;
- sigemptyset(&(sa.sa_mask));
- sigaddset(&(sa.sa_mask), SIGCHLD);
- sigaction(SIGCHLD, &sa, NULL);
-
- /*
- * construct global "masked_sigs" used in nfs_start.c
- */
+ /* construct global "masked_sigs" used in nfs_start.c */
sigemptyset(&masked_sigs);
+ sigaddset(&masked_sigs, SIGINT);
+ sigaddset(&masked_sigs, SIGTERM);
sigaddset(&masked_sigs, SIGHUP);
sigaddset(&masked_sigs, SIGCHLD);
- sigaddset(&masked_sigs, SIGTERM);
- sigaddset(&masked_sigs, SIGINT);
-#else /* not HAVE_SIGACTION */
- (void) signal(SIGCHLD, sigchld);
-#endif /* not HAVE_SIGACTION */
+#endif /* HAVE_SIGACTION */
/*
* Fix-up any umask problems. Most systems default
* SUCH DAMAGE.
*
*
- * $Id: get_args.c,v 1.34 2005/07/26 01:48:13 ezk Exp $
+ * $Id: get_args.c,v 1.35 2005/08/02 01:28:57 ezk Exp $
*
*/
#ifdef MOUNT_TABLE_ON_FILE
if (amuDebug(D_MTAB))
- if(gopt.debug_mtab_file)
+ if (gopt.debug_mtab_file)
mnttab_file_name = gopt.debug_mtab_file; /* user supplied debug mtab path */
else
mnttab_file_name = DEBUG_MNTTAB_FILE; /* default debug mtab path */
* SUCH DAMAGE.
*
*
- * $Id: restart.c,v 1.12 2005/01/18 03:01:24 ib42 Exp $
+ * $Id: restart.c,v 1.13 2005/08/02 01:28:57 ezk Exp $
*
*/
void
restart(void)
{
- /*
- * Read the existing mount table
- */
mntlist *ml, *mlp;
/*
- * For each entry, find nfs, ufs or auto mounts
- * and create a partial am_node to represent it.
+ * Read the existing mount table. For each entry, find nfs, ufs or auto
+ * mounts and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
void
restart_automounter_nodes(void)
{
- /*
- * Read the existing mount table
- */
mntlist *ml, *mlp;
-
- /* Reasonably sized list of restarted nfs ports */
+ /* reasonably sized list of restarted nfs ports */
u_short old_ports[256];
- {
- int i;
- for (i = 0; i < 256; i++)
- old_ports[i] = 0;
- }
+
+ memset((voidp) &old_ports, 0, sizeof(u_short) * 256);
/*
- * For each entry, find nfs, ufs or auto mounts
- * and create a partial am_node to represent it.
+ * Read the existing mount table. For each entry, find nfs, ufs or auto
+ * mounts and create a partial am_node to represent it.
*/
for (mlp = ml = read_mtab("restart", mnttab_file_name);
mlp;
mlp = mlp->mnext) {
mntent_t *me = mlp->mnt;
am_ops *fs_ops = 0;
+ char *colon;
+ long pid;
+ u_short port;
+ int err;
- if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
- /*
- * NFS entry, or possibly an Amd entry...
- * The mnt_fsname for daemon mount points is
- * host:(pidXXX)
- * or (seen on Solaris)
- * host:daemon(pidXXX)
- */
- char *colon = strchr(me->mnt_fsname, ':');
- if (colon && strstr(colon, "(pid")) {
- long pid;
- u_short port;
- int err = 1;
+ if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
+ continue; /* to next mlp */
+ /*
+ * NFS entry, or possibly an Amd entry...
+ * The mnt_fsname for daemon mount points is
+ * host:(pidXXX)
+ * or (seen on Solaris)
+ * host:daemon(pidXXX)
+ */
+ colon = strchr(me->mnt_fsname, ':');
+ if (!colon || !strstr(colon, "(pid"))
+ continue;
+ /* if got here, then we matched an existing Amd mount point */
+ err = 1;
- plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
+ plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
- /* Is the old automounter still alive? */
- if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
- plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
- goto give_up;
- }
- if (kill(pid, 0) != -1 || errno != ESRCH) {
- plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
- goto give_up;
- }
-
- /*
- * Do we have a map for this mount point?
- * Who cares, we'll restart anyway -- getting ESTALE
- * is way better than hanging.
- */
+ /* Is the old automounter still alive? */
+ if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) {
+ plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname);
+ goto give_up;
+ }
+ if (kill(pid, 0) != -1 || errno != ESRCH) {
+ plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid);
+ goto give_up;
+ }
- /* Can we restart it? Only if it tells us what port it was using... */
- if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
- plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
- goto give_up;
- }
+ /*
+ * Do we have a map for this mount point? Who cares, we'll restart
+ * anyway -- getting ESTALE is way better than hanging.
+ */
- /* Maybe we already own that port... */
- if (port != nfs_port) {
- int i;
- for (i = 0; i < 256; i++) {
- if (old_ports[i] == port ||
- old_ports[i] == 0)
- break;
- }
- if (i == 256) {
- plog(XLOG_WARNING, "Too many open ports (256)");
- goto give_up;
- }
+ /* Can we restart it? Only if it tells us what port it was using... */
+ if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) {
+ plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname);
+ goto give_up;
+ }
- if (old_ports[i] == 0) {
- int soNFS;
- SVCXPRT *nfsxprt;
- if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
- plog(XLOG_WARNING, "Can't bind to port %u", port);
- goto give_up;
- }
- old_ports[i] = nfs_port = port;
- }
- }
- err = 0;
+ /* Maybe we already own that port... */
+ if (port != nfs_port) {
+ int i;
+ for (i = 0; i < 256; i++) {
+ if (old_ports[i] == port ||
+ old_ports[i] == 0)
+ break;
+ }
+ if (i == 256) {
+ plog(XLOG_WARNING, "Too many open ports (256)");
+ goto give_up;
+ }
- give_up:
- if (err) {
- plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
- fs_ops = &amfs_link_ops;
- } else {
- fs_ops = &amfs_toplvl_ops;
+ if (old_ports[i] == 0) {
+ int soNFS;
+ SVCXPRT *nfsxprt;
+ if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) {
+ plog(XLOG_WARNING, "Can't bind to port %u", port);
+ goto give_up;
}
-
- restart_fake_mntfs(me, fs_ops);
+ old_ports[i] = nfs_port = port;
}
}
- }
+ err = 0;
- /*
- * Free the mount list
- */
+ give_up:
+ if (err) {
+ plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir);
+ fs_ops = &amfs_link_ops;
+ } else {
+ fs_ops = &amfs_toplvl_ops;
+ }
+
+ restart_fake_mntfs(me, fs_ops);
+ } /* end of "for (mlp" */
+
+ /* free the mount list */
free_mntlist(ml);
}
* SUCH DAMAGE.
*
*
- * $Id: mtab_file.c,v 1.15 2005/03/04 18:42:43 ezk Exp $
+ * $Id: mtab_file.c,v 1.16 2005/08/02 01:28:57 ezk Exp $
*
*/
* Release file lock, by closing the file
*/
if (mnt_file) {
+ dlog("unlock_mntlist: releasing");
endmntent(mnt_file);
mnt_file = 0;
}
* SUCH DAMAGE.
*
*
- * $Id: mtab_isc3.c,v 1.11 2005/04/07 05:50:38 ezk Exp $
+ * $Id: mtab_isc3.c,v 1.12 2005/08/02 01:28:57 ezk Exp $
*
*/
void
unlock_mntlist(void)
{
+ dlog("unlock_mntlist: releasing");
unlockmnttab();
}
*
* %W% (Berkeley) %G%
*
- * $Id: mtab_linux.c,v 1.2 2005/06/25 19:03:05 ezk Exp $
+ * $Id: mtab_linux.c,v 1.3 2005/08/02 01:28:57 ezk Exp $
*
*/
# define PROC_MOUNTS "/proc/mounts"
-static FILE *mnt_file;
+static FILE *mnt_file = NULL;
/* Information about mtab. ------------------------------------*/
static int have_mtab_info = 0;
static int var_mtab_does_not_exist = 0;
static int var_mtab_is_a_symlink = 0;
/* Flag for already existing lock file. */
static int we_created_lockfile = 0;
-/* Flag to indicate that signals have been set up. */
-static int signals_have_been_setup = 0;
static int lockfile_fd = -1;
}
-#if 0
-static int
-mtab_does_not_exist(void)
-{
- get_mtab_info();
- return var_mtab_does_not_exist;
-}
-#endif
-
static int
mtab_is_a_symlink(void)
{
}
-/* Ensure that the lock is released if we are interrupted. */
-static void
-handler (int sig)
-{
- unlock_mntlist();
- plog(XLOG_ERROR, "%s", sys_siglist[sig]);
- exit(1);
-}
-
-
static void
setlkw_timeout(int sig)
{
/* nothing, fcntl will fail anyway */
}
+
/*
* Create the lock file.
* The lock file will be removed if we catch a signal or when we exit.
#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d"
int
-lock_mtab (void)
+lock_mtab(void)
{
int tries = 100000, i;
char *linktargetfile;
- if (!signals_have_been_setup) {
- int sig = 0;
- struct sigaction sa;
-
- sa.sa_handler = handler;
- sa.sa_flags = 0;
- sigfillset (&sa.sa_mask);
-
- while (sigismember (&sa.sa_mask, ++sig) != -1
- && sig != SIGCHLD) {
- if (sig == SIGALRM)
- sa.sa_handler = setlkw_timeout;
- else
- sa.sa_handler = handler;
- sigaction (sig, &sa, (struct sigaction *) 0);
- }
- signals_have_been_setup = 1;
- }
+ /*
+ * Redhat's original code set a signal handler called "handler()" for all
+ * non-ALRM signals. The handler called unlock_mntlist(), plog'ed the
+ * signal name, and then exit(1)! Never, ever, exit() from inside a
+ * utility function. This messed up Amd's careful signal-handling code,
+ * and caused Amd to abort uncleanly only any other "innocent" signal
+ * (even simple SIGUSR1), leaving behind a hung Amd mnt point. That code
+ * should have at least restored the signal handlers' states upon a
+ * successful mtab unlocking. Anyway, that handler was unnecessary,
+ * because will call unlock_mntlist() properly anyway on exit.
+ */
+ setup_sighandler(SIGALRM, setlkw_timeout);
/* somewhat clumsy, but some ancient systems do not have snprintf() */
/* use 20 as upper bound for the length of %d output */
* Filesystem full?
*/
plog(XLOG_ERROR, "can't create lock file %s: %s (use -n flag to override)",
- linktargetfile, strerror (errsv));
+ linktargetfile, strerror(errsv));
}
close(i);
j = link(linktargetfile, MOUNTED_LOCK);
errsv = errno;
-#if 0
- if (j != 0)
- sched_yield();
- (void) unlink(linktargetfile);
-#endif
-
if (j < 0 && errsv != EEXIST) {
(void) unlink(linktargetfile);
plog(XLOG_ERROR, "can't link lock file %s: %s ",
- MOUNTED_LOCK, strerror (errsv));
+ MOUNTED_LOCK, strerror(errsv));
return 0;
}
- lockfile_fd = open (MOUNTED_LOCK, O_WRONLY);
+ lockfile_fd = open(MOUNTED_LOCK, O_WRONLY);
if (lockfile_fd < 0) {
int errsv = errno;
/* Strange... Maybe the file was just deleted? */
if (j == 0) {
/* We made the link. Now claim the lock. */
- if (fcntl (lockfile_fd, F_SETLK, &flock) == -1) {
+ if (fcntl(lockfile_fd, F_SETLK, &flock) == -1) {
int errsv = errno;
plog(XLOG_ERROR, "Can't lock lock file %s: %s",
- MOUNTED_LOCK, strerror (errsv));
+ MOUNTED_LOCK, strerror(errsv));
/* proceed, since it was us who created the lockfile anyway */
}
we_created_lockfile = 1;
/* Someone else made the link. Wait. */
alarm(LOCK_TIMEOUT);
- if (fcntl (lockfile_fd, F_SETLKW, &flock) == -1) {
+ if (fcntl(lockfile_fd, F_SETLKW, &flock) == -1) {
int errsv = errno;
(void) unlink(linktargetfile);
plog(XLOG_ERROR, "can't lock lock file %s: %s",
MOUNTED_LOCK, (errno == EINTR) ?
- "timed out" : strerror (errsv));
+ "timed out" : strerror(errsv));
return 0;
}
alarm(0);
FILE *mfp = 0;
if (mnt_file) {
-# ifdef DEBUG
dlog("Forced close on %s in read_mtab", mnttabname);
-# endif /* DEBUG */
endmntent(mnt_file);
mnt_file = 0;
}
void
unlock_mntlist(void)
{
+ if (mnt_file || we_created_lockfile)
+ dlog("unlock_mntlist: releasing");
if (mnt_file) {
endmntent(mnt_file);
mnt_file = 0;
if (we_created_lockfile) {
close(lockfile_fd);
lockfile_fd = -1;
- unlink (MOUNTED_LOCK);
+ unlink(MOUNTED_LOCK);
we_created_lockfile = 0;
}
}
* SUCH DAMAGE.
*
*
- * $Id: mtab_mach3.c,v 1.13 2005/03/04 18:42:43 ezk Exp $
+ * $Id: mtab_mach3.c,v 1.14 2005/08/02 01:28:57 ezk Exp $
*
*/
* Release file lock, by closing the file
*/
if (mnt_file) {
+ dlog("unlock_mntlist: releasing");
endmntent(mnt_file);
mnt_file = 0;
}
* SUCH DAMAGE.
*
*
- * $Id: am_utils.h,v 1.69 2005/07/26 01:48:13 ezk Exp $
+ * $Id: am_utils.h,v 1.70 2005/08/02 01:28:58 ezk Exp $
*
*/
extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto);
extern long get_server_pid(void);
extern int xsnprintf(char *str, size_t size, const char *format, ...);
+extern void setup_sighandler(int signum, void (*handler)(int));
#ifdef MOUNT_TABLE_ON_FILE
* SUCH DAMAGE.
*
*
- * $Id: xutil.c,v 1.39 2005/07/26 01:48:13 ezk Exp $
+ * $Id: xutil.c,v 1.40 2005/08/02 01:28:58 ezk Exp $
*
*/
unregister_amq();
}
}
+
+#ifdef MOUNT_TABLE_ON_FILE
+ /*
+ * Call unlock_mntlist to free any important resources such as an on-disk
+ * lock file (/etc/mtab~).
+ */
+ unlock_mntlist();
+#endif /* MOUNT_TABLE_ON_FILE */
+
if (foreground) {
plog(XLOG_INFO, "Finishing with status %d", rc);
} else {
dlog("background process exiting with status %d", rc);
}
-
+ /* bye bye... */
exit(rc);
}
va_end(ap);
return ret;
}
+
+
+/* setup a single signal handler */
+void
+setup_sighandler(int signum, void (*handler)(int))
+{
+#ifdef HAVE_SIGACTION
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = 0; /* unnecessary */
+ sa.sa_handler = handler;
+ sigemptyset(&(sa.sa_mask)); /* probably unnecessary too */
+ sigaddset(&(sa.sa_mask), signum);
+ sigaction(signum, &sa, NULL);
+#else /* not HAVE_SIGACTION */
+ (void) signal(signum, handler);
+#endif /* not HAVE_SIGACTION */
+}
+
+