Date: Tue, 28 Aug 2001 17:54:34 -0400 (EDT) From: Jeff Fellin <jkf@research.bell-labs.com> To: freebsd-current@FreeBSD.ORG Cc: mflaster@research.bell-labs.com, eran@research.bell-labs.com Subject: linux threads and fclose lock problem Message-ID: <200108282154.RAA15501@zydeco.research.bell-labs.com>
next in thread | raw e-mail | index | archive | help
The following test program hangs on current from 8/20/2001. The program hangs in the fprintf to the function testThread(), instead of running to completion. If the call in main to fclose() of an unrelated file descriptor is removed the program runs to completion. >From tracing code, it appears that fclose.c locks the file, does some stuff, and then *tries* to unlock the file. But while _flockfile is called, _funlockfile is *not*. (The source for fclose.c calls FUNLOCKFILE(fp) - don't know where FUNLOCKFILE is defined.) So, a lock gets left open. Because these are recursive locks, further I/Os from the same thread are OK, but any IO from a different thread block forever. If the fclose is removed, the program works fine or setting the value of __isthreaded to zero. #include <stdio.h> #include <pthread.h> extern int __isthreaded; void *testThread(void *param) { const char *fn = "/tmp/file_to_write"; FILE *fo = fopen(fn, "w"); printf("testThread __isthreaded = %d\n", __isthreaded); printf ("Writing to file %s\n", fn); fprintf(fo, "Test line\n"); printf ("Finished writing to file %s\n", fn); return NULL; } int main() { const char *fn = "/tmp/foobar"; FILE *fi = fopen(fn, "r"); printf("main __isthreaded = %d\n", __isthreaded); if (!fi) { printf ("%s must exist for this test to work\n", fn); exit(0); } printf ("We opened %s, fd of %d\n", fn, fi->_file); fclose(fi); printf("main after fclose __isthreaded = %d\n", __isthreaded); printf ("File is closed\n"); pthread_t tid; pthread_create(&tid, NULL, testThread, (void*)NULL); pthread_join(tid, NULL); } Here's the output: ----------- main __isthreaded = 1 We opened /tmp/foobar, fd of 3 3, 671604288, 1 - Locking fd main after fclose __isthreaded = 1 File is closed testThread __isthread = 1 Writing to file /tmp/file_to_write 5, 3208641568, 2 - Locking fd 671604288 - File is locked by another thread File is locked: 671644044, 3208642568 Did insert: 671644044 About to suspend:671644044 ----------- Changing the value of __isthreaded to 0 in main produces the expected output: ----------- main __isthreaded = 0 We opened /tmp/foobar, fd of 3 main after fclose __isthreaded = 0 File is closed testThread __isthread = 0 Writing to file /tmp/file_to_write Finished writing to file /tmp/file_to_write ----------- In the default case fclose leaves a lock open so when the other thread attempts file/IO it is suspended waiting for the other thread to release the lock. However the other thread doesn't know it has a lock. So, a lock gets left open. Because these are recursive locks, further I/Os from the same thread are OK, but any IO from a different thread block forever. This is with linuxthreads 2.2.3_1. The compile lines are: g++ -ofclose-test.o -c -g -D_THREAD_SAFE \ -I/usr/local/include/pthread/linuxthreads \ -D_PTHREADS -D__USE_UNIX98 fclose-test.cpp g++ -o fclose-test.exe fclose-test.o -g -L/usr/local/lib -llthread -llgcc_r To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108282154.RAA15501>