How to use __DYNAMIC_REENT__ correctly in multithreaded applications?
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.
> 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:
>>> 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.
More information about the Newlib