libc_r: threaded application could stuck in accept(2)
Ruslan Ermilov
ru at FreeBSD.org
Fri May 30 12:30:37 PDT 2003
On Fri, May 30, 2003 at 08:16:41PM +0300, Ruslan Ermilov wrote:
> On Fri, May 30, 2003 at 07:07:23PM +0300, Enache Adrian wrote:
> > On Fri, May 30, 2003 at 05:35:41PM +0300, Ruslan Ermilov wrote:
> > > We had a bug in our threaded application that would mistakenly close
> > > the descriptor 0, and this triggers a bug in libc_r which I will try
> > > to describe below.
> > ...
> > > Some important notes: this bug is only applicable to descriptors
> > > 0 - 2 (stdio set), and might have something to do with the code
> > > in uthread_fd.c. If you remove two lines that free the descriptor
> > > 0 in the attached test case, the bug won't manifest itself.
> >
> > please have a look at
> >
> > http://www.freebsd.org/cgi/query-pr.cgi?pr=51535
> >
> Thanks, I had this same patch in my first version of the fix.
> Yes it works too, but do you have an insight what's going on
> without these fixes so that the 0..2 descriptors are left in
> a blocking mode? I just can't get it where this happens.
>
OK, I now know what's going on here. Without patches, a
second close(0) calls _FDLOCK(0, ...) which calls
_thread_fd_table_init(0). In this functions, the
following condition becomes false
/* Get the flags for the file: */
if (((fd >= 3) || (_pthread_stdio_flags[fd] == -1)) &&
(entry->flags = __sys_fcntl(fd, F_GETFL, 0)) == -1) {
ret = -1;
}
due to _pthread_stdio_flags[0] != -1, and we succeed
to the "else" block which eventually installs the "entry"
as _thread_fd_table[0].
Then, the call to socket() calls _thread_fd_table_init(0)
again, but since it detects that the memory is already
allocated (for non-existing descriptor 0), it doesn't
try to set it to non-blocking mode.
With my patch, we just don't allow the second call to
_thread_fd_table_init(0) when descriptor 0 doesn't exist.
With your patch that resets _pthread_stdio_flags[0] to -1
on close, attempting to close(0) for the second time
evaluates the condition above to true, and then
__sys_fcntl(0, F_GETFL, 0) returns -1 (EBADF), and
then the "entry" is free()'ed. Then, on the next socket()
call, _thread_fd_table_init(0) allocates the memory
for fd 0, and sets it to non-blocking mode.
> P.S. I will commit both patches after the freeze is over.
>
Your patch also fixes the bug you mentioned, so I will
commit both patches.
Cheers,
--
Ruslan Ermilov Sysadmin and DBA,
ru at sunbay.com Sunbay Software AG,
ru at FreeBSD.org FreeBSD committer.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20030530/58b1a9c5/attachment.bin
More information about the freebsd-hackers
mailing list