How to use __DYNAMIC_REENT__ correctly in multithreaded applications?
J. Johnston
jjohnstn@redhat.com
Thu Aug 21 23:39:00 GMT 2003
Thomas,
Just to let you know that I am working on a fix for this problem.
It is a little more complex than first thought but I have it working
for your test scenario.
I have eliminated use of the fp->_data pointer which is pointless.
There is no point performing future tasks based on the reentrant struct for
the file when it was opened. That cures one problem. I fixed the
CHECK_INIT macro to use _REENT for now. I have also done a whole bunch
of cleaning up with regards to _r functions. There is still some cleanup
that could be done, but for a DYNAMIC_REENT or single-threaded app, everything
should be working much better. Finally, I have added the _GLOBAL_REENT
macro to be used for manipulating the file list. Keeping everything but
the thread's std streams on the main thread helps when exiting and performing
a closeall.
I hope to check in the patch tomorrow.
-- 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