Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uuid1 creation doesn't close files - hits file descriptor limit #1

Open
tomrittervg opened this issue Jul 11, 2012 · 1 comment
Open

Comments

@tomrittervg
Copy link

I have a daemon that calls uuid.uuid1() occassionally. It eventually hits the file descriptor limit because, as far as I can tell, /var/lib/libuuid/clock.txt is never closed:

lrwx------ 1 root root 64 Jul 11 18:27 304 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 305 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 306 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:27 307 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 308 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:27 309 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 31 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 310 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:27 311 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 312 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 313 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:27 314 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 315 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:25 316 -> /var/lib/libuuid/clock.txt
lrwx------ 1 root root 64 Jul 11 18:27 317 -> /var/lib/libuuid/clock.txt

I looked at libuuid, and found this function:

e2fsprogs-8b3114e\gen_uuid.c

static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
             uint16_t *ret_clock_seq, int *num)
{
    THREAD_LOCAL int        adjustment = 0;
    THREAD_LOCAL struct timeval last = {0, 0};
    THREAD_LOCAL int        state_fd = -2;
    THREAD_LOCAL FILE       *state_f;
    THREAD_LOCAL uint16_t       clock_seq;
    struct timeval          tv;
    struct flock            fl;
    uint64_t            clock_reg;
    mode_t              save_umask;
    int             len;

    if (state_fd == -2) {
        save_umask = umask(0);
        state_fd = open("/var/lib/libuuid/clock.txt",
                O_RDWR|O_CREAT, 0660);
        (void) umask(save_umask);
        state_f = fdopen(state_fd, "r+");
        if (!state_f) {
            close(state_fd);
            state_fd = -1;
        }
    }
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;
    fl.l_pid = 0;
    if (state_fd >= 0) {
        rewind(state_f);
        while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
            if ((errno == EAGAIN) || (errno == EINTR))
                continue;
            fclose(state_f);
            close(state_fd);
            state_fd = -1;
            break;
        }
    }
    if (state_fd >= 0) {
        unsigned int cl;
        unsigned long tv1, tv2;
        int a;

        if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
               &cl, &tv1, &tv2, &a) == 4) {
            clock_seq = cl & 0x3FFF;
            last.tv_sec = tv1;
            last.tv_usec = tv2;
            adjustment = a;
        }
    }

    if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
        get_random_bytes(&clock_seq, sizeof(clock_seq));
        clock_seq &= 0x3FFF;
        gettimeofday(&last, 0);
        last.tv_sec--;
    }

try_again:
    gettimeofday(&tv, 0);
    if ((tv.tv_sec < last.tv_sec) ||
        ((tv.tv_sec == last.tv_sec) &&
         (tv.tv_usec < last.tv_usec))) {
        clock_seq = (clock_seq+1) & 0x3FFF;
        adjustment = 0;
        last = tv;
    } else if ((tv.tv_sec == last.tv_sec) &&
        (tv.tv_usec == last.tv_usec)) {
        if (adjustment >= MAX_ADJUSTMENT)
            goto try_again;
        adjustment++;
    } else {
        adjustment = 0;
        last = tv;
    }

    clock_reg = tv.tv_usec*10 + adjustment;
    clock_reg += ((uint64_t) tv.tv_sec)*10000000;
    clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;

    if (num && (*num > 1)) {
        adjustment += *num - 1;
        last.tv_usec += adjustment / 10;
        adjustment = adjustment % 10;
        last.tv_sec += last.tv_usec / 1000000;
        last.tv_usec = last.tv_usec % 1000000;
    }

    if (state_fd > 0) {
        rewind(state_f);
        len = fprintf(state_f, 
                  "clock: %04x tv: %016lu %08lu adj: %08d\n",
                  clock_seq, last.tv_sec, last.tv_usec, adjustment);
        fflush(state_f);
        if (ftruncate(state_fd, len) < 0) {
            fprintf(state_f, "                   \n");
            fflush(state_f);
        }
        rewind(state_f);
        fl.l_type = F_UNLCK;
        fcntl(state_fd, F_SETLK, &fl);
    }

    *clock_high = clock_reg >> 32;
    *clock_low = clock_reg;
    *ret_clock_seq = clock_seq;
    return 0;
}

This doesn't seem the close the file descriptor state_fd - but I wanted another opinion. Does this make sense? Is it an issue with libuuid or with python, or am I doing something wrong...?

@tomrittervg
Copy link
Author

Apparently this is a known issue: http://comments.gmane.org/gmane.linux.utilities.util-linux-ng/4771 and there no no fix coming down the pipe. Perhaps this is worth a comment somewhere? I'm going to have to switch to another type of library code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant