Skip site navigation (1)Skip section navigation (2)
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>