|
| 1 | +---------- |
| 2 | +Known bugs |
| 3 | +---------- |
| 4 | + |
| 5 | +1. Not strictly a bug, more of a gotcha. |
| 6 | + |
| 7 | + Under MS VC++ (only tested with version 6.0), a term_func |
| 8 | + set via the standard C++ set_terminate() function causes the |
| 9 | + application to abort. |
| 10 | + |
| 11 | + Notes from the MSVC++ manual: |
| 12 | + 1) A term_func() should call exit(), otherwise |
| 13 | + abort() will be called on return to the caller. |
| 14 | + A call to abort() raises SIGABRT and the default signal handler |
| 15 | + for all signals terminates the calling program with |
| 16 | + exit code 3. |
| 17 | + 2) A term_func() must not throw an exception. Therefore |
| 18 | + term_func() should not call pthread_exit(), which |
| 19 | + works by throwing an exception (pthreadVCE or pthreadVSE) |
| 20 | + or by calling longjmp (pthreadVC). |
| 21 | + |
| 22 | + Workaround: avoid using pthread_exit() in C++ applications. Exit |
| 23 | + threads by dropping through the end of the thread routine. |
| 24 | + |
| 25 | +2. Cancellation problems in optimised code |
| 26 | + - Milan Gardian |
| 27 | + |
| 28 | + This is suspected to be a compiler bug in VC6.0, and also seen in |
| 29 | + VC7.0 and VS .NET 2003. The GNU C++ compiler does not have a problem |
| 30 | + with this, and it has been reported that the Intel C++ 8.1 compiler |
| 31 | + and Visual C++ 2005 Express Edition Beta2 pass tests\semaphore4.c |
| 32 | + (which exposes the bug). |
| 33 | + |
| 34 | + Workaround [rpj - 2 Feb 2002] |
| 35 | + ----------------------------- |
| 36 | + [Please note: this workaround did not solve a similar problem in |
| 37 | + snapshot-2004-11-03 or later, even though similar symptoms were seen. |
| 38 | + tests\semaphore4.c fails in that snapshot for the VCE version of the |
| 39 | + DLL.] |
| 40 | + |
| 41 | + The problem disappears when /Ob0 is used, i.e. /O2 /Ob0 works OK, |
| 42 | + but if you want to use inlining optimisation you can be much more |
| 43 | + specific about where it's switched off and on by using a pragma. |
| 44 | + |
| 45 | + So the inlining optimisation is interfering with the way that cleanup |
| 46 | + handlers are run. It appears to relate to auto-inlining of class methods |
| 47 | + since this is the only auto inlining that is performed at /O1 optimisation |
| 48 | + (functions with the "inline" qualifier are also inlined, but the problem |
| 49 | + doesn't appear to involve any such functions in the library or testsuite). |
| 50 | + |
| 51 | + In order to confirm the inlining culprit, the following use of pragmas |
| 52 | + eliminate the problem but I don't know how to make it transparent, putting |
| 53 | + it in, say, pthread.h where pthread_cleanup_push defined as a macro. |
| 54 | + |
| 55 | + #pragma inline_depth(0) |
| 56 | + pthread_cleanup_push(handlerFunc, (void *) &arg); |
| 57 | + |
| 58 | + /* ... */ |
| 59 | + |
| 60 | + pthread_cleanup_pop(0); |
| 61 | + #pragma inline_depth() |
| 62 | + |
| 63 | + Note the empty () pragma value after the pop macro. This resets depth to the |
| 64 | + default. Or you can specify a non-zero depth here. |
| 65 | + |
| 66 | + The pragma is also needed (and now used) within the library itself wherever |
| 67 | + cleanup handlers are used (condvar.c and rwlock.c). |
| 68 | + |
| 69 | + Use of these pragmas allows compiler optimisations /O1 and /O2 to be |
| 70 | + used for either or both the library and applications. |
| 71 | + |
| 72 | + Experimenting further, I found that wrapping the actual cleanup handler |
| 73 | + function with #pragma auto_inline(off|on) does NOT work. |
| 74 | + |
| 75 | + MSVC6.0 doesn't appear to support the C99 standard's _Pragma directive, |
| 76 | + however, later versions may. This form is embeddable inside #define |
| 77 | + macros, which would be ideal because it would mean that it could be added |
| 78 | + to the push/pop macro definitions in pthread.h and hidden from the |
| 79 | + application programmer. |
| 80 | + |
| 81 | + [/rpj] |
| 82 | + |
| 83 | + Original problem description |
| 84 | + ---------------------------- |
| 85 | + |
| 86 | + The cancellation (actually, cleanup-after-cancel) tests fail when using VC |
| 87 | + (professional) optimisation switches (/O1 or /O2) in pthreads library. I |
| 88 | + have not investigated which concrete optimisation technique causes this |
| 89 | + problem (/Og, /Oi, /Ot, /Oy, /Ob1, /Gs, /Gf, /Gy, etc.), but here is a |
| 90 | + summary of builds and corresponding failures: |
| 91 | + |
| 92 | + * pthreads VSE (optimised tests): OK |
| 93 | + * pthreads VCE (optimised tests): Failed "cleanup1" test (runtime) |
| 94 | + |
| 95 | + * pthreads VSE (DLL in CRT, optimised tests): OK |
| 96 | + * pthreads VCE (DLL in CRT, optimised tests): Failed "cleanup1" test |
| 97 | + (runtime) |
| 98 | + |
| 99 | + Please note that while in VSE version of the pthreads library the |
| 100 | + optimisation does not really have any impact on the tests (they pass OK), in |
| 101 | + VCE version addition of optimisation (/O2 in this case) causes the tests to |
| 102 | + fail uniformly - either in "cleanup0" or "cleanup1" test cases. |
| 103 | + |
| 104 | + Please note that all the tests above use default pthreads DLL (no |
| 105 | + optimisations, linked with either static or DLL CRT, based on test type). |
| 106 | + Therefore the problem lies not within the pthreads DLL but within the |
| 107 | + compiled client code (the application using pthreads -> involvement of |
| 108 | + "pthread.h"). |
| 109 | + |
| 110 | + I think the message of this section is that usage of VCE version of pthreads |
| 111 | + in applications relying on cancellation/cleanup AND using optimisations for |
| 112 | + creation of production code is highly unreliable for the current version of |
| 113 | + the pthreads library. |
| 114 | + |
| 115 | +3. The Borland Builder 5.5 version of the library produces memory read exceptions |
| 116 | +in some tests. |
| 117 | + |
| 118 | +4. pthread_barrier_wait() can deadlock if the number of potential calling |
| 119 | +threads for a particular barrier is greater than the barrier count parameter |
| 120 | +given to pthread_barrier_init() for that barrier. |
| 121 | + |
| 122 | +This is due to the very lightweight implementation of pthread-win32 barriers. |
| 123 | +To cope with more than "count" possible waiters, barriers must effectively |
| 124 | +implement all the same safeguards as condition variables, making them much |
| 125 | +"heavier" than at present. |
| 126 | + |
| 127 | +The workaround is to ensure that no more than "count" threads attempt to wait |
| 128 | +at the barrier. |
| 129 | + |
| 130 | +5. Canceling a thread blocked on pthread_once appears not to work in the MSVC++ |
| 131 | +version of the library "pthreadVCE.dll". The test case "once3.c" hangs. I have no |
| 132 | +clues on this at present. All other versions pass this test ok - pthreadsVC.dll, |
| 133 | +pthreadsVSE.dll, pthreadsGC.dll and pthreadsGCE.dll. |
0 commit comments