+4080. [func] Completed change #4022, adding a "lock-file" option
+ to named.conf to override the default lock file,
+ in addition to the "named -X <filename>" command
+ line option. Setting the lock file to "none"
+ using either method disables the check completely.
+ [RT #37908]
+
4079. [func] Preserve the case of the ownername of records to
the RRset level. [RT #37442]
nta-recheck 300;\n\
notify-rate 20;\n\
# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
+# lock-file \"" NS_LOCALSTATEDIR "/run/named/named.lock\";\n\
port 53;\n\
prefetch 2 9;\n\
recursing-file \"named.recursing\";\n\
EXTERN const char * ns_g_defaultsessionkeyfile
INIT(NS_LOCALSTATEDIR "/run/named/"
"session.key");
-EXTERN const char * ns_g_singletonfile INIT(NS_LOCALSTATEDIR
+EXTERN const char * ns_g_defaultlockfile INIT(NS_LOCALSTATEDIR
"/run/named/"
"named.lock");
+EXTERN isc_boolean_t ns_g_forcelock INIT(ISC_FALSE);
#if NS_RUN_PID_DIR
EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
isc_uint16_t session_keybits;
isc_boolean_t interface_auto;
unsigned char secret[32]; /*%< Source Identity Token */
+
+ char * lockfile;
};
#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
/* Obsolete. No longer in use. Ignore. */
break;
case 'X':
- ns_g_singletonfile = isc_commandline_argument;
+ ns_g_forcelock = ISC_TRUE;
+ if (strcasecmp(isc_commandline_argument, "none") != 0)
+ ns_g_defaultlockfile = isc_commandline_argument;
+ else
+ ns_g_defaultlockfile = NULL;
break;
case 'F':
/* Reserved for FIPS mode */
parse_command_line(argc, argv);
- if (!ns_os_issingleton(ns_g_singletonfile))
- ns_main_earlyfatal("could not lock %s; "
- "another named process may be running",
- ns_g_singletonfile);
-
/*
* Warn about common configuration error.
*/
<para>
Acquire a lock on the specified file at runtime; this
helps to prevent duplicate <command>named</command> instances
- from running simultaneously. If not specified via this option,
- the default lockfile is <filename>/var/run/named/named.lock</filename>.
+ from running simultaneously.
+ Use of this option overrides the <command>lock-file</command>
+ option in <filename>named.conf</filename>.
+ If set to <literal>none</literal>, the lock file check
+ is disabled.
</para>
</listitem>
</varlistentry>
return (n);
}
+static isc_result_t
+check_lockfile(ns_server_t *server, const cfg_obj_t *config,
+ isc_boolean_t first_time)
+{
+ isc_result_t result;
+ const char *filename = NULL;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *options;
+ const cfg_obj_t *obj;
+ int i;
+
+ i = 0;
+ options = NULL;
+ result = cfg_map_get(config, "options", &options);
+ if (result == ISC_R_SUCCESS)
+ maps[i++] = options;
+ maps[i++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ obj = NULL;
+ (void) ns_config_get(maps, "lock-file", &obj);
+
+ if (!first_time) {
+ if (obj != NULL && !cfg_obj_isstring(obj) &&
+ server->lockfile != NULL &&
+ strcmp(cfg_obj_asstring(obj), server->lockfile) != 0)
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING,
+ "changing 'lock-file' "
+ "has no effect until the "
+ "server is restarted");
+
+ return (ISC_R_SUCCESS);
+ }
+
+ if (obj != NULL) {
+ if (cfg_obj_isvoid(obj)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "skipping lock-file check ");
+ return (ISC_R_SUCCESS);
+ } else if (ns_g_forcelock) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "'lock-file' has no effect "
+ "because the server was run with -X");
+ server->lockfile = isc_mem_strdup(server->mctx,
+ ns_g_defaultlockfile);
+ } else {
+ filename = cfg_obj_asstring(obj);
+ server->lockfile = isc_mem_strdup(server->mctx,
+ filename);
+ }
+
+ if (server->lockfile == NULL)
+ return (ISC_R_NOMEMORY);
+ }
+
+ if (ns_g_forcelock && ns_g_defaultlockfile != NULL) {
+ INSIST(server->lockfile == NULL);
+ server->lockfile = isc_mem_strdup(server->mctx,
+ ns_g_defaultlockfile);
+ }
+
+ if (server->lockfile == NULL)
+ return (ISC_R_SUCCESS);
+
+ if (ns_os_issingleton(server->lockfile))
+ return (ISC_R_SUCCESS);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not lock %s; another named "
+ "process may be running", server->lockfile);
+ return (ISC_R_FAILURE);
+}
+
static isc_result_t
load_configuration(const char *filename, ns_server_t *server,
isc_boolean_t first_time)
*/
set_limits(maps);
+ /*
+ * Check the process lockfile.
+ */
+ CHECK(check_lockfile(server, config, first_time));
+
/*
* Check if max number of open sockets that the system allows is
* sufficiently large. Failing this condition is not necessarily fatal,
server->session_keyalg = DST_ALG_UNKNOWN;
server->session_keybits = 0;
+ server->lockfile = NULL;
+
server->magic = NS_SERVER_MAGIC;
*serverp = server;
}
isc_mem_free(server->mctx, server->hostname);
if (server->server_id != NULL)
isc_mem_free(server->mctx, server->server_id);
+ if (server->lockfile != NULL)
+ isc_mem_free(server->mctx, server->lockfile);
if (server->zonemgr != NULL)
dns_zonemgr_detach(&server->zonemgr);
isc_result_totext(result));
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
ISC_LOG_CRITICAL, "exiting (due to fatal error)");
+ ns_os_shutdown();
exit(1);
}
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: os.c,v 1.107 2011/03/02 00:02:54 marka Exp $ */
-
/*! \file */
#include <config.h>
#endif
static char *pidfile = NULL;
+static char *lockfile = NULL;
static int devnullfd = -1;
static int singletonfd = -1;
pidfile = NULL;
}
+static void
+cleanup_lockfile(void) {
+ if (singletonfd != -1) {
+ close(singletonfd);
+ singletonfd = -1;
+ }
+
+ if (lockfile != NULL) {
+ int n = unlink(lockfile);
+ if (n == -1 && errno != ENOENT)
+ ns_main_earlywarning("unlink '%s': failed", lockfile);
+ free(lockfile);
+ lockfile = NULL;
+ }
+}
+
+/*
+ * Ensure that a directory exists.
+ * NOTE: This function overwrites the '/' characters in 'filename' with
+ * nulls. The caller should copy the filename to a fresh buffer first.
+ */
static int
mkdirpath(char *filename, void (*report)(const char *, ...)) {
char *slash = strrchr(filename, '/');
isc_boolean_t
ns_os_issingleton(const char *filename) {
+ char strbuf[ISC_STRERRORSIZE];
struct flock lock;
if (singletonfd != -1)
return (ISC_TRUE);
+ if (strcasecmp(filename, "none") == 0)
+ return (ISC_TRUE);
+
+ /*
+ * Make the containing directory if it doesn't exist.
+ */
+ lockfile = strdup(filename);
+ if (lockfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("couldn't allocate memory for '%s': %s",
+ filename, strbuf);
+ } else {
+ int ret = mkdirpath(lockfile, ns_main_earlywarning);
+ if (ret == -1) {
+ ns_main_earlywarning("couldn't create '%s'", filename);
+ cleanup_lockfile();
+ return (ISC_FALSE);
+ }
+ }
+
/*
* ns_os_openfile() uses safeopen() which removes any existing
* files. We can't use that here.
*/
singletonfd = open(filename, O_WRONLY | O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (singletonfd == -1)
+ if (singletonfd == -1) {
+ cleanup_lockfile();
return (ISC_FALSE);
+ }
memset(&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;
ns_os_shutdown(void) {
closelog();
cleanup_pidfile();
-
- if (singletonfd != -1) {
- close(singletonfd);
- singletonfd = -1;
- }
+ cleanup_lockfile();
}
isc_result_t
#include <named/ntservice.h>
+static char *lockfile = NULL;
static char *pidfile = NULL;
static int devnullfd = -1;
static int singletonfd = -1;
ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH);
lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH);
+ ns_g_defaultlockfile = isc_ntpaths_get(NAMED_LOCK_PATH);
ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH);
ns_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH);
pidfile = NULL;
}
+static void
+cleanup_lockfile(void) {
+ if (singletonfile != -1) {
+ close(singletonfd);
+ singletonfd = -1;
+ }
+
+ if (lockfile != NULL) {
+ int n = unlink(lockfile);
+ if (n == -1 && errno != ENOENT)
+ ns_main_earlywarning("unlink '%s': failed", lockfile);
+ free(lockfile);
+ lockfile = NULL;
+ }
+}
+
FILE *
ns_os_openfile(const char *filename, int mode, isc_boolean_t switch_user) {
char strbuf[ISC_STRERRORSIZE];
if (singletonfd != -1)
return (ISC_TRUE);
+ if (strcasecmp(filename, "none") == 0)
+ return (ISC_TRUE);
+
+ lockfile = strdup(filename);
+ if (lockfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("couldn't allocate memory for '%s': %s",
+ filename, strbuf);
+ }
+
/*
* ns_os_openfile() uses safeopen() which removes any existing
* files. We can't use that here.
*/
singletonfd = open(filename, O_WRONLY | O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (singletonfd == -1)
+ if (singletonfd == -1) {
+ cleanup_lockfile();
return (ISC_FALSE);
+ }
memset(&o, 0, sizeof(o));
/* Expect ERROR_LOCK_VIOLATION if already locked */
if (!LockFileEx((HANDLE) _get_osfhandle(singletonfd),
LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
0, 0, 1, &o)) {
- close(singletonfd);
- singletonfd = -1;
+ cleanup_lockfile();
return (ISC_FALSE);
}
return (ISC_TRUE);
}
+
void
ns_os_shutdown(void) {
closelog();
rm -f */named.memstats
rm -f */named*.run
-rm -f ns*/named.lock ns*/.nolock
+rm -f ns*/named.lock ns*/named*.pid ns*/other.lock
--- /dev/null
+/*
+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ port 5300;
+ pid-file "named4.pid";
+ lock-file none;
+ listen-on { 10.53.0.2; 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+ dnssec-validation no;
+};
--- /dev/null
+#!/bin/sh -e
+#
+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+$SHELL clean.sh
n=`expr $n + 1`
echo "I:verifying that named checks for conflicting listeners ($n)"
ret=0
-(cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X .nolock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
+(cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
sleep 2
grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
[ -s ns2/named2.pid ] && kill -15 `cat ns2/named2.pid`
(cd ns2; $NAMED -c named-alt2.conf -D ns2-extra-2 -X named.lock -m record,size,mctx -d 99 -g -U 4 >> named3.run 2>&1 & )
sleep 2
grep "another named process" ns2/named3.run > /dev/null || ret=1
-[ -s ns2/named3.pid ] && kill -15 `cat ns3/named2.pid`
+[ -s ns2/named3.pid ] && kill -15 `cat ns2/named3.pid`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo "I:verifying that 'lock-file none' disables process check ($n)"
+ret=0
+(cd ns2; $NAMED -c named-alt3.conf -D ns2-extra-3 -m record,size,mctx -d 99 -g -U 4 >> named4.run 2>&1 & )
+sleep 2
+grep "another named process" ns2/named4.run > /dev/null && ret=1
+[ -s ns2/named4.pid ] && kill -15 `cat ns2/named4.pid`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+
exit $status
<optional> cache-file <replaceable>path_name</replaceable>; </optional>
<optional> dump-file <replaceable>path_name</replaceable>; </optional>
<optional> bindkeys-file <replaceable>path_name</replaceable>; </optional>
+ <optional> lock-file <replaceable>path_name</replaceable>; </optional>
<optional> secroots-file <replaceable>path_name</replaceable>; </optional>
<optional> session-keyfile <replaceable>path_name</replaceable>; </optional>
<optional> session-keyname <replaceable>key_name</replaceable>; </optional>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>lock-file</command></term>
+ <listitem>
+ <para>
+ The pathname of a file on which <command>named</command> will
+ attempt to acquire a file lock when starting up for
+ the first time; if unsuccessful, the server will
+ will terminate, under the assumption that another
+ server is already running. If not specified, the default is
+ <filename>/var/run/named/named.lock</filename>.
+ </para>
+ <para>
+ Specifying <command>lock-file none</command> disables the
+ use of a lock file. <command>lock-file</command> is
+ ignored if named was run using the <option>-X</option>
+ option, which overrides it. Changes to
+ <command>lock-file</command> are ignored if
+ <command>named</command> is being reloaded or
+ reconfigured; it is only effective when the server is
+ first started up.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>pid-file</command></term>
<listitem>
other name server processes are running before starting up.
This is implemented in two ways: 1) by refusing to start
if the configured network interfaces all return "address
- in use", and 2) by acquiring a file lock on
- <filename>/var/run/named/named.lock</filename>, or on a different
- file specified via the <command>named -X</command> command
- line option.
+ in use", and 2) by attempting to acquire a lock on a file
+ specified by the <command>lock-file</option> option or
+ the <command>-X</command> command line option. The
+ default lock file is
+ <filename>/var/run/named/named.lock</filename>.
+ Specifying <literal>none</literal> will disable the lock
+ file check.
</para>
</listitem>
<listitem>
RNDC_CONF_PATH,
NAMED_PID_PATH,
LWRESD_PID_PATH,
+ NAMED_LOCK_PATH,
LOCAL_STATE_DIR,
SYS_CONF_DIR,
RNDC_KEY_PATH,
static char rndc_confFile[MAX_PATH];
static char ns_defaultpidfile[MAX_PATH];
static char lwresd_defaultpidfile[MAX_PATH];
+static char ns_lockfile[MAX_PATH];
static char local_state_dir[MAX_PATH];
static char sys_conf_dir[MAX_PATH];
static char rndc_keyFile[MAX_PATH];
strcpy(lwresd_defaultpidfile, namedBase);
strcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid");
+ strcpy(ns_lockfile, namedBase);
+ strcat(ns_lockfile, "\\etc\\named.lock");
+
strcpy(local_state_dir, namedBase);
strcat(local_state_dir, "\\bin");
case LWRESD_PID_PATH:
return (lwresd_defaultpidfile);
break;
+ case NAMED_LOCK_PATH:
+ return (ns_lockfile);
+ break;
case LOCAL_STATE_DIR:
return (local_state_dir);
break;
{ "keep-response-order", &cfg_type_bracketed_aml, 0 },
{ "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
{ "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
+ { "lock-file", &cfg_type_qstringornone, 0 },
#ifdef ISC_PLATFORM_USESIT
{ "sit-secret", &cfg_type_sstring, 0 },
#else