summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-09-01 20:06:26 +0000
committerNick Mathewson <nickm@torproject.org>2008-09-01 20:06:26 +0000
commitf80ac31d742c2d86f1812b895ef61a5885e2447e (patch)
tree9b223723aced9e7a8acc55044120cc406c77bd9b /src/or
parent6a29ad853b630a1970fd95e17ecd79306e7c39e6 (diff)
downloadtor-f80ac31d742c2d86f1812b895ef61a5885e2447e.tar.gz
tor-f80ac31d742c2d86f1812b895ef61a5885e2447e.zip
Add a lockfile to the Tor data directory to avoid situations where two Tors start with the same datadir, or where a --list-fingerprints races with a server to create keys, or such.
svn:r16722
Diffstat (limited to 'src/or')
-rw-r--r--src/or/config.c11
-rw-r--r--src/or/main.c48
-rw-r--r--src/or/or.h12
-rw-r--r--src/or/router.c11
4 files changed, 77 insertions, 5 deletions
diff --git a/src/or/config.c b/src/or/config.c
index 52c7f8b8a4..7d9dc64b7d 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1172,6 +1172,11 @@ options_act(or_options_t *old_options)
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
+ if (running_tor && !have_lockfile()) {
+ if (try_locking(options, 1) < 0)
+ return -1;
+ }
+
if (consider_adding_dir_authorities(options, old_options) < 0)
return -1;
@@ -4883,10 +4888,10 @@ get_or_state(void)
* Note: Consider using the get_datadir_fname* macros in or.h.
*/
char *
-get_datadir_fname2_suffix(const char *sub1, const char *sub2,
- const char *suffix)
+options_get_datadir_fname2_suffix(or_options_t *options,
+ const char *sub1, const char *sub2,
+ const char *suffix)
{
- or_options_t *options = get_options();
char *fname = NULL;
size_t len;
tor_assert(options);
diff --git a/src/or/main.c b/src/or/main.c
index c3f902e776..1d57cff5ed 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1850,6 +1850,54 @@ tor_init(int argc, char *argv[])
return 0;
}
+static tor_lockfile_t *lockfile = NULL;
+
+int
+try_locking(or_options_t *options, int err_if_locked)
+{
+ if (lockfile)
+ return 0;
+ else {
+ char *fname = options_get_datadir_fname2_suffix(options, "lock",NULL,NULL);
+ int already_locked = 0;
+ tor_lockfile_t *lf = tor_lockfile_lock(fname, 0, &already_locked);
+ tor_free(fname);
+ if (!lf) {
+ if (err_if_locked && already_locked) {
+ int r;
+ log_warn(LD_GENERAL, "It looks like another Tor process is running "
+ "with the same data directory. Waiting 5 seconds to see "
+ "if it goes away.");
+ sleep(5);
+ r = try_locking(options, 0);
+ if (r<0) {
+ log_err(LD_GENERAL, "No, it's still there. Exiting.");
+ exit(0);
+ }
+ return r;
+ }
+ return -1;
+ }
+ lockfile = lf;
+ return 0;
+ }
+}
+
+int
+have_lockfile(void)
+{
+ return lockfile != NULL;
+}
+
+void
+release_lockfile(void)
+{
+ if (lockfile) {
+ tor_lockfile_unlock(lockfile);
+ lockfile = NULL;
+ }
+}
+
/** Free all memory that we might have allocated somewhere.
* If <b>postfork</b>, we are a worker process and we want to free
* only the parts of memory that we won't touch. If !<b>postfork</b>,
diff --git a/src/or/or.h b/src/or/or.h
index ab7e98d883..a84bd9b9d6 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2781,8 +2781,11 @@ config_line_t *option_get_assignment(or_options_t *options,
const char *key);
int options_save_current(void);
const char *get_torrc_fname(void);
-char *get_datadir_fname2_suffix(const char *sub1, const char *sub2,
- const char *suffix);
+char *options_get_datadir_fname2_suffix(or_options_t *options,
+ const char *sub1, const char *sub2,
+ const char *suffix);
+#define get_datadir_fname2_suffix(sub1, sub2, suffix) \
+ options_get_datadir_fname2_suffix(get_options(), (sub1), (sub2), (suffix))
/** Return a newly allocated string containing datadir/sub1. See
* get_datadir_fname2_suffix. */
#define get_datadir_fname(sub1) get_datadir_fname2_suffix((sub1), NULL, NULL)
@@ -3493,6 +3496,11 @@ void dns_servers_relaunch_checks(void);
void control_signal_act(int the_signal);
void handle_signals(int is_parent);
+
+int try_locking(or_options_t *options, int err_if_locked);
+int have_lockfile(void);
+void release_lockfile(void);
+
void tor_cleanup(void);
void tor_free_all(int postfork);
diff --git a/src/or/router.c b/src/or/router.c
index 842cb7b52a..4c85a7b2ab 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -235,6 +235,17 @@ init_key_from_file(const char *fname, int generate, int severity)
goto error;
case FN_NOENT:
if (generate) {
+ if (!have_lockfile()) {
+ if (try_locking(get_options(), 0)<0) {
+ /* Make sure that --list-fingerprint only creates new keys
+ * if there is no possibility for a deadlock. */
+ log(severity, LD_FS, "Another Tor process has locked \"%s\". Not "
+ "writing any new keys.", fname);
+ /*XXXX The 'other process' might make a key in a second or two;
+ * maybe we should wait for it. */
+ goto error;
+ }
+ }
log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
fname);
if (crypto_pk_generate_key(prkey)) {