unfortunately, that one still fails:

h% 8c -w nsec.c
h% 8l nsec.8
h% 8.out
1307094033073099818
1307094033079570483
0

my approach is a little different.

in the library:

vlong
nsec(void)
{
        uchar b[8];
        vlong t;
        int fd, n;

        fd = open("/dev/bintime", OREAD);
        if(fd < 0)
                return 0;
        t = 0;
        if(pread(fd, b, sizeof(b), 0) == sizeof(b))
                be2vlong(&t, b);
        close(fd);
        return t;
}

what about applications that need to get the nsec frequently?
*in those applications*, i write

extern int timefd;

void
applicationinit(void)
{
        timefd = open("/dev/bintime", OREAD|OCEXEC);
        if(timefd < 0)
                sysfatal("can't open /dev/bintime: %r");
        ...
}

vlong
readnsec(void)
{
        uchar b[8];
        vlong t;

        if(pread(timefd, b, sizeof(b), 0) != sizeof(b))
                return 0;       /* or sysfatal as you like */
        be2vlong(&t, b);
        return t;
}

that's the first phase. then since there are a few applications that do that,
it might be better to account for that in the library:

extern  vlong   readnsec(int fd);

it's similar to the above, but takes fd as a parameter.
alternatively you could have a function that unpacked and returned the
other values in bintime as well (clock ticks, and clock frequency), if you're 
keen.

the original flaw was having a library routine that messed about
with a process's file descriptors without any idea of context,
and worse, stored the file descriptor in a hidden location,
with no way to mark it later as redundant or invalid.
that makes the library function fragile, and you can't fix it from outside
the library. in the failing example above, i wrote:

        print("%llud\n", xnsec());
        print("%llud\n", xnsec());
        for(i = 2; i < 20; i++)
                close(i);
        print("%lld\n", xnsec());

(where xnsec is the most recently proposed version of nsec).
being able to close files seems reasonable to me, but invalidates the
file descriptor that nsec had stashed away. worse, i could open another
file later that had the same index for xnsec to try to read.

lots of other things could be changed, such as making rfork and close
into functions that wrap _rfork and _close system calls, so they can
notify other library functions to clean up their fd debris, but perhaps
it's better not to create the potential for debris.

other interfaces are possible that make the file descriptor visible
to the application, and any of those would be fine.

Reply via email to