How to use __DYNAMIC_REENT__ correctly in multithreaded applications?

J. Johnston jjohnstn@redhat.com
Sat Aug 23 17:56:00 GMT 2003


A monster patch has been checked in.  I found a problem in stdio64/fseeko64.c
using struct stat when calling _fstat64_r. I could not switch to use stat64
as Cygwin has not defined it externally.  For now, stdio64/fseeko64.c will use _fstat_r
instead of _fstat64_r.

I have rebuilt on linux and cygwin.  Give it a try.

There is still some reentrancy fixups that could be done but they will
not have any impact on a __DYNAMIC_REENT__ or non-threaded build which
work correctly by virtue of using _REENT.

-- Jeff J.

Thomas Pfaff wrote:
> I can not do it this way because it must be fixed for cygwin and not on 
> an application level.
> 
> As far as i can see the only problem with __DYNAMIC_REENT__ is this 
> stdio related stuff, so i would suggest to fix it temporarly in newlib.
> 
> My proposal is:
> 
> Create a new macro _GLOBAL_REENT which returns _impure_ptr.
> Change all functions in stdio to use _GLOBAL_REENT instead of _REENT 
> until there is a better solution.
> 
> Thomas
> 
> J. Johnston wrote:
> 
>> It's a design problem that isn't the fault of __DYNAMIC_REENT__ and
>> is going to require a little bit of thought.  One way you might bypass 
>> this problem is
>> to create an fopen stub for your application and have it call _fopen_r 
>> with the default global reentrancy struct.
>>
>> -- Jeff J.
>>
>> Thomas Pfaff wrote:
>>
>>> Hello,
>>>
>>> some time ago i have added a __DYNAMIC_REENT__ to the cygwin part of
>>> config.h. The main purpose was to get thread safe errnos (without this
>>> define errno is stored process global in _impure_ptr).
>>>
>>> Now the reent structure for every thread is thread local and will be
>>> destroyed when the thread has terminated. A __getreent function was
>>> implemented to get the thread local reent.
>>>
>>> This leads to following problem:
>>>
>>> Each FILE structure contains a pointer to the reent structure of the
>>> thread that initially opened the file. If the thread terminates than the
>>>   reent pointer will point to an invalid address.
>>>
>>> Here is a simple testcase to illustrate this probleme:
>>>
>>> #include <stdio.h>
>>> #include <pthread.h>
>>>
>>> static FILE *fp;
>>>
>>> static void *threadfunc (void *parm)
>>> {
>>>   fp = fopen ("/tmp/testreent", "w");
>>>   return NULL;
>>> }
>>>
>>> int main(void)
>>> {
>>>   pthread_t thread;
>>>
>>>   pthread_create (&thread, NULL, threadfunc, NULL);
>>>   pthread_join (thread, NULL);
>>>
>>>   fprintf (fp, "test");
>>>   fclose (fp);
>>>
>>>   return 0;
>>> }
>>>
>>> A thread opens a file and terminates immediately. The mainthread will
>>> try to write to the opened file and segfaults in the CHECK_INIT macro in
>>> fwrite since the data part of the FILE pointer is no longer valid.
>>>
>>> I am a bit clueless now:
>>> How was DYNAMIC_REENT stuff meant to work  ?
>>>
>>> IMHO the only way to get this working is to remove the reent part in the
>>> FILE structure, but there might be a better solution.
>>>
>>> TIA,
>>> Thomas
>>
>>
>>
> 
> 



More information about the Newlib mailing list