* libuuid clock.txt fd leaks
@ 2011-09-21 16:58 Tim Pepper
2011-09-21 20:26 ` Ted Ts'o
0 siblings, 1 reply; 7+ messages in thread
From: Tim Pepper @ 2011-09-21 16:58 UTC (permalink / raw)
To: util-linux
libuuid's gen_uuid.c:get_clock() goes to some length to try to reuse
its fd and avoid repeated opens of /var/lib/libuuid/clock.txt and also
to be thread safe. But the current implementation must lead to fd
leakage in multithreaded applications. This has been reported
multiple places as the gen_uuid.c file seems to have been reused in
various open source projects. But I don't see mention of this issue
in the util-linux archives.
Some mentions I've found:
http://sourceforge.net/tracker/index.php?func=detail&aid=3276476&group_id=2406&atid=102406
https://github.com/samuel/python-gearman/pull/3
And it's come into my lap by way of some complicated Java application
I can't claim to understand, but they error on too many open files and
note via lsof that opens of clock.txt grow unbounded during their
runtime.
While googling around I also noticed the C++98 spec (well maybe
anyway...as referenced here:
http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/C_002b_002b98-Thread_002dLocal-Edits.html#C_002b_002b98-Thread_002dLocal-Edits)
includes the idea that things in TLS shouldn't have non-trivial
destructors. Shows at least that somebody's thought about the
problem. I'd guess having to have something know to do fclose() /
close() on parts of the TLS counts as non-trivial and shouldn't be
done.
The sourceforge.net link above includes a number of suggested options.
And there's also just the simple implementation option for
get_clock() that doesn't have the fd as static much less TLS and
opens/closes at each invocation. That maybe comes with a noticable
performance hit for some types of users and I don't really know the
full list of possible use cases here...do some people really need that
high performance uuid generation? Either way, the "right" general
solution isn't immediately obvious to me so I thought I'd see what
others here thought...
Tim
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 16:58 libuuid clock.txt fd leaks Tim Pepper
@ 2011-09-21 20:26 ` Ted Ts'o
2011-09-21 21:15 ` Ted Ts'o
2011-09-21 22:02 ` Tim Pepper
0 siblings, 2 replies; 7+ messages in thread
From: Ted Ts'o @ 2011-09-21 20:26 UTC (permalink / raw)
To: Tim Pepper; +Cc: util-linux
On Wed, Sep 21, 2011 at 09:58:21AM -0700, Tim Pepper wrote:
> The sourceforge.net link above includes a number of suggested options.
> And there's also just the simple implementation option for
> get_clock() that doesn't have the fd as static much less TLS and
> opens/closes at each invocation. That maybe comes with a noticable
> performance hit for some types of users and I don't really know the
> full list of possible use cases here...do some people really need that
> high performance uuid generation? Either way, the "right" general
> solution isn't immediately obvious to me so I thought I'd see what
> others here thought...
Part of the problem is that the uuid library was originally designed
non-thread-using libraries, and I originally was trying to force all
programs to link against -lpthread. (Remember, libuuid as found in
e2fsprogs predates Linux having a standardized threads support, or any
threads support at all.)
Personally, I think threads are evil, and avoid them like the plague,
so I'm not up on the latest threads requirements, but at least at one
point, if a shared library used threads all of the programs that
called said shared library had to link against pthreads and #include
pthread.h, and have errno redefined, etc. (Remember we need to worry
about making things work both for the static and shared linking case.)
So the reason why I put in THREAD_LOCAL was it was the simplest way to
avoid problems without having access to mutexes and without having to
drag in the whole posix threads mess and inflicting it on all of
libuuid's callers.
Unfortunately, it didn't occur to me that people would write programs
where they spawned jillions of threads and then abandon them, causing
the fd leak that would eventually kill the program. (See my belief
that Posix Threads are evil.)
It may be that the right answer is to create a separate library which
is used for threading programs --- or develop a completely thread-safe
API for threaded progams, and keep the old API for
sane^H^H^H^Hsingle-threaded programs.
- Ted
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 20:26 ` Ted Ts'o
@ 2011-09-21 21:15 ` Ted Ts'o
2011-09-21 22:02 ` Tim Pepper
1 sibling, 0 replies; 7+ messages in thread
From: Ted Ts'o @ 2011-09-21 21:15 UTC (permalink / raw)
To: Tim Pepper; +Cc: util-linux
On Wed, Sep 21, 2011 at 04:26:20PM -0400, Ted Ts'o wrote:
> Part of the problem is that the uuid library was originally designed
> non-thread-using libraries, and I originally was trying to force all
Sigh, s/to force/to avoid forcing/
> programs to link against -lpthread. (Remember, libuuid as found in
> e2fsprogs predates Linux having a standardized threads support, or any
> threads support at all.)
- Ted
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 20:26 ` Ted Ts'o
2011-09-21 21:15 ` Ted Ts'o
@ 2011-09-21 22:02 ` Tim Pepper
2011-09-21 22:19 ` Tim Pepper
2011-09-21 22:24 ` Ted Ts'o
1 sibling, 2 replies; 7+ messages in thread
From: Tim Pepper @ 2011-09-21 22:02 UTC (permalink / raw)
To: Ted Ts'o; +Cc: util-linux
On Wed, Sep 21, 2011 at 1:26 PM, Ted Ts'o <tytso@mit.edu> wrote:
> It may be that the right answer is to create a separate library which
> is used for threading programs --- or develop a completely thread-safe
> API for threaded progams, and keep the old API for
> sane^H^H^H^Hsingle-threaded programs.
I don't think this is so much about API. The documented behavior for
uuid_generate() and its siblings does not necessarily need to change here.
I view this mostly as an internal implementation detail.
The existing code optimizes to reuse the fd and avoids repeated
open/close calls for a given caller. If the variables are static,
they're not thread safe. So they became thread local. At that point
"interesting" threads may become a problem because of the lack of
destructor to do closes. But...
Is the original optimization really needed? If not you avoid the whole
problem...no static, no TLS, no fd left open.
And it looks like a similar thing happens in get_random_fd(), fwiw.
I wonder who would whinge on performance if the open/close simply
happened everytime? Ie: remove initial state_fd=-2 and its associated
special casing.
Tim
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 22:02 ` Tim Pepper
@ 2011-09-21 22:19 ` Tim Pepper
2011-09-21 22:24 ` Ted Ts'o
1 sibling, 0 replies; 7+ messages in thread
From: Tim Pepper @ 2011-09-21 22:19 UTC (permalink / raw)
To: Tim Pepper; +Cc: Ted Ts'o, util-linux
On Wed 21 Sep at 15:02:48 -0700 tpepper@gmail.com said:
>
> I wonder who would whinge on performance if the open/close simply
> happened everytime? Ie: remove initial state_fd=-2 and its associated
> special casing.
Something sort of like this for get_clock(), completely untested...
--
Tim Pepper <lnxninja@linux.vnet.ibm.com>
IBM Linux Technology Center
--- gen_uuid.c.orig 2011-09-16 14:14:58.902434595 -0700
+++ gen_uuid.c 2011-09-21 15:06:35.271419101 -0700
@@ -316,57 +316,48 @@ static int get_node_id(unsigned char *no
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;
+ int adjustment = 0;
+ struct timeval last = {0, 0};
+ int fd;
+ FILE *f;
+ uint16_t clock_seq;
struct timeval tv;
uint64_t clock_reg;
mode_t save_umask;
int len;
int ret = 0;
-
- 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);
- if (state_fd != -1) {
- state_f = fdopen(state_fd, "r+");
- if (!state_f) {
- close(state_fd);
- state_fd = -1;
- ret = -1;
- }
+ unsigned int cl;
+ unsigned long tv1, tv2;
+ int a;
+
+ save_umask = umask(0);
+ fd = open("/var/lib/libuuid/clock.txt",
+ O_RDWR|O_CREAT, 0660);
+ (void) umask(save_umask);
+ if (fd != -1) {
+ f = fdopen(fd, "r+");
+ if (!f) {
+ close(fd);
+ return -1;
}
- else
- ret = -1;
}
- if (state_fd >= 0) {
- rewind(state_f);
- while (flock(state_fd, LOCK_EX) < 0) {
- if ((errno == EAGAIN) || (errno == EINTR))
- continue;
- fclose(state_f);
- close(state_fd);
- state_fd = -1;
- ret = -1;
- break;
- }
+ else
+ return -1;
+
+ while (flock(fd, LOCK_EX) < 0) {
+ if ((errno == EAGAIN) || (errno == EINTR))
+ continue;
+ fclose(f);
+ close(fd);
+ return -1;
}
- 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 (fscanf(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)) {
@@ -406,19 +397,18 @@ try_again:
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);
- flock(state_fd, LOCK_UN);
- }
+ rewind(f);
+ len = fprintf(f,
+ "clock: %04x tv: %016lu %08lu adj: %08d\n",
+ clock_seq, last.tv_sec, last.tv_usec, adjustment);
+ fflush(f);
+ if (ftruncate(fd, len) < 0) {
+ fprintf(f, " \n");
+ fflush(f);
+ }
+ fclose(f);
+ flock(fd, LOCK_UN);
+ close(fd);
*clock_high = clock_reg >> 32;
*clock_low = clock_reg;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 22:02 ` Tim Pepper
2011-09-21 22:19 ` Tim Pepper
@ 2011-09-21 22:24 ` Ted Ts'o
2011-09-21 22:32 ` Tim Pepper
1 sibling, 1 reply; 7+ messages in thread
From: Ted Ts'o @ 2011-09-21 22:24 UTC (permalink / raw)
To: Tim Pepper; +Cc: util-linux
On Wed, Sep 21, 2011 at 03:02:48PM -0700, Tim Pepper wrote:
> Is the original optimization really needed? If not you avoid the whole
> problem...no static, no TLS, no fd left open.
> I wonder who would whinge on performance if the open/close simply
> happened everytime? Ie: remove initial state_fd=-2 and its associated
> special casing.
There are programs out there that generate literally tens of thousands
of UUID's per second. One example of such a program filed high
priority bugs with both RHEL and SLES because it wasn't fast enough
and the uuid library was slowing down the setup time of an
commercially important Enterprise Resource Planning product by hours.
The reason why I implemented uuidd was specifically to help out this
product and this company. Partially because it was economically
important to Red Hat, SLES, and IBM (who was my employer at the time),
and partially because I had a soft spot for this company, to which I had
helped add Kerberos authentication and was very supportive of Linux in
the mid 1990's, before Linux had been discovered by big business.
But yeah, there are people and companies who really care about
libuuid's performance.
- Ted
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: libuuid clock.txt fd leaks
2011-09-21 22:24 ` Ted Ts'o
@ 2011-09-21 22:32 ` Tim Pepper
0 siblings, 0 replies; 7+ messages in thread
From: Tim Pepper @ 2011-09-21 22:32 UTC (permalink / raw)
To: Ted Ts'o; +Cc: Tim Pepper, util-linux
On Wed 21 Sep at 18:24:12 -0400 tytso@mit.edu said:
>
> There are programs out there that generate literally tens of thousands
> of UUID's per second.
That's what I worried. I figured you wouldn't have done this if that
weren't the case. One can hope though right? Perhaps for the use case
I'm looking at they don't need performance as much as they need the fd
not to leak. We'll see...
--
Tim Pepper <lnxninja@linux.vnet.ibm.com>
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-09-21 22:32 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-21 16:58 libuuid clock.txt fd leaks Tim Pepper
2011-09-21 20:26 ` Ted Ts'o
2011-09-21 21:15 ` Ted Ts'o
2011-09-21 22:02 ` Tim Pepper
2011-09-21 22:19 ` Tim Pepper
2011-09-21 22:24 ` Ted Ts'o
2011-09-21 22:32 ` Tim Pepper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox