python-libuuid icon indicating copy to clipboard operation
python-libuuid copied to clipboard

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

Open tomrittervg opened this issue 12 years ago • 1 comments

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 avatar Jul 11 '12 18:07 tomrittervg

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.

tomrittervg avatar Jul 11 '12 19:07 tomrittervg