This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Oh dear, pthreads and stdio still not mt-safe :-(


    Hi everyone (and Arash in particular!),

  Re: my earlier message [at
http://sources.redhat.com/ml/cygwin/2004-01/msg00072.html ]

  Well, I thought the latest snapshot had solved my problem with stdio
getting messed up by threads, but there's still a bug in there somewhere.

  Recall my original testcase: main spawns two threads, each of which does
nothing apart from spit out single chars to stdout at regular intervals. The
foreground then waits for a crlf from stdin (using scanf) and set a global
flag that causes the threads to exit.

  Well, with the latest cygwin dll snapshot, that testcase works fine - or
in any case, it stopped giving SEGVs.  But it turns out to be an accident of
the fixed and deterministic timing relationships between the output from the
various threads.  When I modified the testcase ever so slightly, to randomly
vary the delay between spitting out chars in the spawned threads, it breaks
again.  It doesn't crash, but the output gets mangled and corrupted.

  Here's an example: mttest1.exe is my original testcase, with intervals of
313ms and 257ms in the threads that print 'W' and 'R' respectively; in
mttest2.exe, both threads output chars at random intervals between 250ms -
506ms.  Now watch them run:

---snip---
dk@mace /test/mt-test/test1> ./mttest1
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
RWRWRWRWRRW
****AFTER SCANF
RLeaving thread func2!
WLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest1
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
RWRWRWRWRRWRWRWRWRWRRWRWRWRWRRWRWRWRWRWRRWRWRWRWRWR
****AFTER SCANF
RLeaving thread func2!
WLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---

  OK, that's the non-random version working fine.  Now here's the one with
random delays.  Note that as the code doesn't seed the prng, the sequence is
the same every time.  Note also that rand_r isn't exported in cygwin.din, so
I had to snarf the code directly from  the cygwin/newlib source... :) I
believe this omission may be accidental, n'est-ce pas?

---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....WRWRWRWRRRRWRWWRWRRW...
****AFTER SCANFs tf2...
RLeaving thread func2!WLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
WRWRWRWRRRRWRWWR
****AFTER SCANF
WRLeaving thread func2!
Leaving thread func2!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
WRWRWRWRRRRWRWWR
****AFTER SCANF
WRLeaving thread func2!
Leaving thread func2!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
WRWRWRWRRRRWRWWRWR
****AFTER SCANF
RLeaving thread func2!
WLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
WRWRWRWRRRRWRWWR
****AFTER SCANF
WRLeaving thread func2!
Leaving thread func2!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---
dk@mace /test/mt-test/test1> ./mttest2.exe
Press return/enter to terminate.....Thread #1 enters tf1...
Thread #2 enters tf2...
WRWRWRWR
****AFTER SCANF
RLeaving thread func2!
LLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
---snip---

  As you can see, during the first run it outputs a spurious cursor-up
character and starts overwriting earlier output.  In the second run the
"Leaving thread func1" message gets dropped and the "Leaving thread func2"
message is duplicated - or perhaps just the '1' gets overwritten by a
spurious '2'.  In the third and fifth runs the same problem occurs as in the
second run; it's completely reproducible by pressing CR just as the WR
characters line up under the word 'enters' in the "Thread #2 enters..."
message.  Only the fourth run appears correct.  In the sixth run, there's a
duplicated L at the start of the "Leaving thread func1" message: probably
one of the 'W' chars got turned to an L.

  And oh dear even more.  I've just seen my original testcase fail, so I
guess even that one wasn't completely fixed after all.  Notice the spurious
cursor-up again:

---snip---
dk@mace /test/mt-test/test1> ./mttest1.exe
Press return/enter to terminate.....RWread #1 enters tf1...
****AFTER SCANFs tf2...
RLeaving thread func2!
WLeaving thread func1!
exit ok
exit 2 ok
thread exticodes $     0x1 $     0x2
dk@mace /test/mt-test/test1> ./mttest1.exe
Press return/enter to terminate.....RWRWRWR#1 enters tf1...
****AFTER SCANFs tf2...
WLeaving thread func1!
exit ok
RLeaving thread func2!
exit 2 ok
thread exticodes $     0x1 $     0x2
dk@mace /test/mt-test/test1>
---snip---

  This post is long enough as it is, so I've omitted my cygcheck output for
the moment, since it's the same as the one in my last post (url at top of
this post), apart from the fact I'm now using the snapshot
cygwin1-20040103.dll.

  Anyway, that all seems to show there's definitely still a bug in there.
I'm pretty sure it's not down to me having accidentally used any non-mt-safe
functions or otherwise not obeyed the C and POSIX specs, and I hope the
reproducibility of these results might help whoever's working in that area
track down the problem, but I'm pretty stumped myself.  Any clues / hints /
suggestions gratefully received.

   cheers,
     DaveK


Attachment: makefile
Description: Binary data

Attachment: mttest1.c
Description: Text document

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]