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, [EMAIL PROTECTED] Sunbay Software AG, [EMAIL PROTECTED] FreeBSD committer.
pgp00000.pgp
Description: PGP signature