Skip to content

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

@tomrittervg

Description

@tomrittervg

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...?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions