From 6e23e5e9e16fb16aafb4ef05ceb3514a02147a21 Mon Sep 17 00:00:00 2001 From: Biswajit Sadhu Date: Thu, 6 Sep 2018 02:51:40 -0700 Subject: [PATCH] lib: Ensure FRR detects running of the second instance of a FRR daemon, doesnot allow it to run. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Solution : The following procedures would be performed : 1. Verify if the pid file for each daemon is present or not. If the file is not present, that means the daemon is getting instantiated for the first time. So let it go ahead. If the file is present proceed to point ‘2’. 2. Try fetching the properties of the pid file. 3. If it has RW lock, that means one instance of this the daemon is already running. So stop moving ahead and do exit() else let it go ahead.
Please note all above procedure happen at the initial state of daemon’s instantiation, much before it starts any session with other process/allocates resources etc.. and this verification do not have any impact of any operations done later, if the verification succeeds. Signed-off-by: bisdhdh sadhub@vmware.com --- lib/libfrr.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/libfrr.c b/lib/libfrr.c index 821c57f37b..115c70f7c9 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -262,12 +262,39 @@ bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len, static struct frr_daemon_info *di = NULL; +static void frr_guard_daemon(void) +{ + int fd; + struct flock lock; + + const char *path = di->pid_file; + fd = open(path, O_RDWR); + if (fd != -1) { + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + if (fcntl(fd, F_GETLK, &lock) < 0) { + flog_err_sys(LIB_ERR_SYSTEM_CALL, + "Could not do F_GETLK pid_file %s (%s), exiting", + path, safe_strerror(errno)); + exit(1); + } else if (lock.l_type == F_WRLCK) { + flog_err_sys(LIB_ERR_SYSTEM_CALL, + "Process %d has a write lock on file %s already! Error : ( %s)", + lock.l_pid, path, safe_strerror(errno)); + exit(1); + } + close(fd); + } +} + void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv) { di = daemon; /* basename(), opencoded. */ char *p = strrchr(argv[0], '/'); + di->progname = p ? p + 1 : argv[0]; umask(0027); @@ -589,6 +616,9 @@ struct thread_master *frr_init(void) zprivs_init(di->privs); + /* Guard to prevent a second instance of this daemon */ + frr_guard_daemon(); + master = thread_master_create(NULL); signal_init(master, di->n_signals, di->signals); -- 2.39.5