Commit f80ac31d authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Add a lockfile to the Tor data directory to avoid situations where two Tors...

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
parent 6a29ad85
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3,6 +3,10 @@ Changes in version 0.2.1.6-alpha - 2008-09-xx
    - Fix compile on OpenBSD 4.4-current. Bugfix on 0.2.1.5-alpha.
      Reported by Tas.

  o Minor features:
    - Use a lockfile to make sure that two Tor processes are not
      simultaneously running with the same datadir.


Changes in version 0.2.1.5-alpha - 2008-08-31
  o Major features:
+1 −1
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h

dnl These headers are not essential

AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h limits.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h inttypes.h utime.h sys/utime.h sys/mman.h netinet/in6.h malloc.h sys/syslimits.h malloc/malloc.h linux/types.h)
AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h limits.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h inttypes.h utime.h sys/utime.h sys/mman.h netinet/in6.h malloc.h sys/syslimits.h malloc/malloc.h linux/types.h sys/file.h)

TOR_CHECK_PROTOTYPE(malloc_good_size, HAVE_MALLOC_GOOD_SIZE_PROTOTYPE,
[#ifdef HAVE_MALLOC_H
+75 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ const char compat_c_id[] =
#ifdef MS_WINDOWS
#include <process.h>
#include <windows.h>
#include <sys/locking.h>
#endif

#ifdef HAVE_UNAME
@@ -98,6 +99,9 @@ const char compat_c_id[] =
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif

#ifdef USE_BSOCKETS
#include <bsocket.h>
@@ -488,6 +492,77 @@ touch_file(const char *fname)
  return 0;
}

struct tor_lockfile_t {
  char *filename;
  int fd;
};

tor_lockfile_t *
tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
{
  tor_lockfile_t *result;
  int fd;
  *locked_out = 0;

  log_info(LD_FS, "Locking \"%s\"", filename);
  fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
  if (fd < 0) {
    log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
             strerror(errno));
    return NULL;
  }
#ifdef WIN32
  _lseek(fd, 0, SEEK_SET);
  if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLOCK, 0) < 0) {
    if (errno != EDEADLOCK)
      log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
    else
      *locked_out = 1;
    close(fd);
    return NULL;
  }
#else
  if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
    if (errno != EWOULDBLOCK)
      log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
    else
      *locked_out = 1;
    close(fd);
    return NULL;
  }
#endif

  result = tor_malloc(sizeof(tor_lockfile_t));
  result->filename = tor_strdup(filename);
  result->fd = fd;
  return result;
}

void
tor_lockfile_unlock(tor_lockfile_t *lockfile)
{
  tor_assert(lockfile);

  log_info(LD_FS, "Unlocking \"%s\"", lockfile->filename);
#ifdef WIN32
  _lseek(fd, 0, SEEK_SET);
  if (_locking(fd, _LK_UNLCK, 0) < 0) {
    log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
             strerror(errno));
  }
#else
  if (flock(lockfile->fd, LOCK_UN) < 0) {
    log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
             strerror(errno));
  }
#endif

  close(lockfile->fd);
  lockfile->fd = -1;
  tor_free(lockfile->filename);
  tor_free(lockfile);
}

#undef DEBUG_SOCKET_COUNTING
#ifdef DEBUG_SOCKET_COUNTING
/** A bitarray of all fds that should be passed to tor_socket_close(). Only
+5 −0
Original line number Diff line number Diff line
@@ -266,6 +266,11 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
int replace_file(const char *from, const char *to);
int touch_file(const char *fname);

typedef struct tor_lockfile_t tor_lockfile_t;
tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
                                  int *locked_out);
void tor_lockfile_unlock(tor_lockfile_t *lockfile);

#ifdef MS_WINDOWS
#define PATH_SEPARATOR "\\"
#else
+8 −3
Original line number Diff line number Diff line
@@ -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,
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);
Loading