Ejemplo n.º 1
0
static void
run_lock_blocks_same_process(void)
{
    struct lockfile *lockfile;

    CHECK(lockfile_lock("file", &lockfile), 0);
    CHECK(lockfile_lock("file", &lockfile), EDEADLK);
    lockfile_unlock(lockfile);
}
Ejemplo n.º 2
0
static void
run_lock_and_unlock_twice(void)
{
    struct lockfile *lockfile;

    CHECK(lockfile_lock("file", &lockfile), 0);
    lockfile_unlock(lockfile);

    CHECK(lockfile_lock("file", &lockfile), 0);
    lockfile_unlock(lockfile);
}
Ejemplo n.º 3
0
static void
run_lock_twice_blocks_other_process(void)
{
    struct lockfile *lockfile, *dummy;

    CHECK(lockfile_lock("file", &lockfile), 0);
    CHECK(lockfile_lock("file", &dummy), EDEADLK);
    if (do_fork() == CHILD) {
        CHECK(lockfile_lock("file", &dummy), EAGAIN);
        exit(11);
    }
}
Ejemplo n.º 4
0
static void
run_lock_and_unlock_allows_other_process(void)
{
    struct lockfile *lockfile;

    CHECK(lockfile_lock("file", &lockfile), 0);
    lockfile_unlock(lockfile);

    if (do_fork() == CHILD) {
        CHECK(lockfile_lock("file", &lockfile), 0);
        exit(11);
    }
}
Ejemplo n.º 5
0
static void
run_lock_blocks_other_process(void)
{
    /* Making this static prevents a memory leak warning from valgrind for the
     * parent process, which cannot easily unlock (and free) 'lockfile' because
     * it can only do so after the child has exited, and it's the caller of
     * this function that does the wait() call. */
    static struct lockfile *lockfile;

    CHECK(lockfile_lock("file", &lockfile), 0);
    if (do_fork() == CHILD) {
        lockfile_unlock(lockfile);
        CHECK(lockfile_lock("file", &lockfile), EAGAIN);
        exit(11);
    }
}
Ejemplo n.º 6
0
/* Checks that locking a dangling symlink works OK.  (It used to hang.) */
static void
run_lock_symlink(void)
{
    struct lockfile *a, *b, *dummy;
    struct stat s;

    /* Create a symlink .a.~lock~ pointing to .b.~lock~. */
    CHECK(symlink(".b.~lock~", ".a.~lock~"), 0);
    CHECK(lstat(".a.~lock~", &s), 0);
    CHECK(S_ISLNK(s.st_mode) != 0, 1);
    CHECK(stat(".a.~lock~", &s), -1);
    CHECK(errno, ENOENT);
    CHECK(stat(".b.~lock~", &s), -1);
    CHECK(errno, ENOENT);

    CHECK(lockfile_lock("a", &a), 0);
    CHECK(lockfile_lock("a", &dummy), EDEADLK);
    CHECK(lockfile_lock("b", &dummy), EDEADLK);
    lockfile_unlock(a);

    CHECK(lockfile_lock("b", &b), 0);
    CHECK(lockfile_lock("b", &dummy), EDEADLK);
    CHECK(lockfile_lock("a", &dummy), EDEADLK);
    lockfile_unlock(b);

    CHECK(lstat(".a.~lock~", &s), 0);
    CHECK(S_ISLNK(s.st_mode) != 0, 1);
    CHECK(stat(".a.~lock~", &s), 0);
    CHECK(S_ISREG(s.st_mode) != 0, 1);
    CHECK(stat(".b.~lock~", &s), 0);
    CHECK(S_ISREG(s.st_mode) != 0, 1);
}
Ejemplo n.º 7
0
/* Checks that locking a file that is itself a symlink yields a lockfile in the
 * directory that the symlink points to, named for the target of the
 * symlink.
 *
 * (That is, if "a" is a symlink to "dir/b", then "a"'s lockfile is named
 * "dir/.b.~lock".) */
static void
run_lock_symlink_to_dir(void)
{
    struct lockfile *a, *dummy;
    struct stat s;

    /* Create a symlink "a" pointing to "dir/b". */
    CHECK(mkdir("dir", 0700), 0);
    CHECK(symlink("dir/b", "a"), 0);
    CHECK(lstat("a", &s), 0);
    CHECK(S_ISLNK(s.st_mode) != 0, 1);

    /* Lock 'a'. */
    CHECK(lockfile_lock("a", &a), 0);
    CHECK(lstat("dir/.b.~lock~", &s), 0);
    CHECK(S_ISREG(s.st_mode) != 0, 1);
    CHECK(lstat(".a.~lock~", &s), -1);
    CHECK(errno, ENOENT);
    CHECK(lockfile_lock("dir/b", &dummy), EDEADLK);

    lockfile_unlock(a);
}
Ejemplo n.º 8
0
static void
run_lock_multiple(void)
{
    struct lockfile *a, *b, *c, *dummy;

    CHECK(lockfile_lock("a", &a), 0);
    CHECK(lockfile_lock("b", &b), 0);
    CHECK(lockfile_lock("c", &c), 0);

    lockfile_unlock(a);
    CHECK(lockfile_lock("a", &a), 0);
    CHECK(lockfile_lock("a", &dummy), EDEADLK);
    lockfile_unlock(a);

    lockfile_unlock(b);
    CHECK(lockfile_lock("a", &a), 0);

    lockfile_unlock(c);
    lockfile_unlock(a);
}
Ejemplo n.º 9
0
Archivo: log.c Proyecto: l8huang/ovs
/* Attempts to open 'name' with the specified 'open_mode'.  On success, stores
 * the new log into '*filep' and returns NULL; otherwise returns NULL and
 * stores NULL into '*filep'.
 *
 * Whether the file will be locked using lockfile_lock() depends on 'locking':
 * use true to lock it, false not to lock it, or -1 to lock it only if
 * 'open_mode' is a mode that allows writing.
 */
struct ovsdb_error *
ovsdb_log_open(const char *name, enum ovsdb_log_open_mode open_mode,
               int locking, struct ovsdb_log **filep)
{
    struct lockfile *lockfile;
    struct ovsdb_error *error;
    struct ovsdb_log *file;
    struct stat s;
    FILE *stream;
    int flags;
    int fd;

    *filep = NULL;

    ovs_assert(locking == -1 || locking == false || locking == true);
    if (locking < 0) {
        locking = open_mode != OVSDB_LOG_READ_ONLY;
    }
    if (locking) {
        int retval = lockfile_lock(name, &lockfile);
        if (retval) {
            error = ovsdb_io_error(retval, "%s: failed to lock lockfile",
                                   name);
            goto error;
        }
    } else {
        lockfile = NULL;
    }

    if (open_mode == OVSDB_LOG_READ_ONLY) {
        flags = O_RDONLY;
    } else if (open_mode == OVSDB_LOG_READ_WRITE) {
        flags = O_RDWR;
    } else if (open_mode == OVSDB_LOG_CREATE) {
#ifndef _WIN32
        if (stat(name, &s) == -1 && errno == ENOENT
            && lstat(name, &s) == 0 && S_ISLNK(s.st_mode)) {
            /* 'name' is a dangling symlink.  We want to create the file that
             * the symlink points to, but POSIX says that open() with O_EXCL
             * must fail with EEXIST if the named file is a symlink.  So, we
             * have to leave off O_EXCL and accept the race. */
            flags = O_RDWR | O_CREAT;
        } else {
            flags = O_RDWR | O_CREAT | O_EXCL;
        }
#else
        flags = O_RDWR | O_CREAT | O_EXCL;
#endif
    } else {
        OVS_NOT_REACHED();
    }
#ifdef _WIN32
    flags = flags | O_BINARY;
#endif
    fd = open(name, flags, 0666);
    if (fd < 0) {
        const char *op = open_mode == OVSDB_LOG_CREATE ? "create" : "open";
        error = ovsdb_io_error(errno, "%s: %s failed", op, name);
        goto error_unlock;
    }

    if (!fstat(fd, &s) && s.st_size == 0) {
        /* It's (probably) a new file so fsync() its parent directory to ensure
         * that its directory entry is committed to disk. */
        fsync_parent_dir(name);
    }

    stream = fdopen(fd, open_mode == OVSDB_LOG_READ_ONLY ? "rb" : "w+b");
    if (!stream) {
        error = ovsdb_io_error(errno, "%s: fdopen failed", name);
        goto error_close;
    }

    file = xmalloc(sizeof *file);
    file->name = xstrdup(name);
    file->lockfile = lockfile;
    file->stream = stream;
    file->prev_offset = 0;
    file->offset = 0;
    file->read_error = NULL;
    file->write_error = false;
    file->mode = OVSDB_LOG_READ;
    *filep = file;
    return NULL;

error_close:
    close(fd);
error_unlock:
    lockfile_unlock(lockfile);
error:
    return error;
}