[Bug libstdc++/31117] New: c++locale.o thread-unsafe in libstdc++
Functions in c++locale.o in libstdc++.a access the errno global int and this is unsafe for use in threaded programs. Yet another object file in the same library references the thread-local errno address function. Impact is minimal, but indicates mixed compilation model object files are linked together into the same library. This situation occurs on several platforms. >From of "nm -g /opt/sfw/lib/libstdc++.a" on Solaris 10 (package SFWgcc34l 3.4.2): /opt/sfw/lib/libstdc++.a[basic_file.o]: [Index] Value SizeType Bind Other Shndx Name [38]| 0| 0|NOTY |GLOB |0|UNDEF |___errno /opt/sfw/lib/libstdc++.a[c++locale.o]: [Index] Value SizeType Bind Other Shndx Name [27]| 0| 0|NOTY |GLOB |0|UNDEF |errno On this platform, both should be referencing ___errno. The same problem appears to exist in libstdc++.so, but it's more difficult to determine which object the reference comes from. It's not clear to me how this problem happens at all, as both basic_file_stdio.cc and c_locale.cc appear to be compiled with the same options yet obviously were not. Although the problem occurs on 3.4 libraries, the relevant files (c_locale.cc, src/Makefile.am) have not to have changed much, so I suspect the problem is still present. Platforms I checked: Solaris 8 SPARC: package SMCgcc342 3.4.2 by Steve Christensen Solaris 10 x86: package SUNWgccruntime 11.10.0 by Sun Solaris 10 SPARC: package SFWgcc34l 3.4.2 by Sun HP-UX 11.11 PA RISC: package GNU_C_C++.GCC_3_4_5 by HP AIX 5.1: (not sure where this one came from, I'm not an AIX wiz) Irix 6.5: (not sure where it came from) Linux RH 9: not a problem, no errno access Mac OS X: not a problem, no errno access Impact Analysis: what trouble can this errno access cause? The functions in c_locale.cc which access errno are templates: __convert_to_v(const char*, float&, ...) __convert_to_v(const char*, double&, ...) __convert_to_v(const char*, long double&, ...) These parse text and convert it to a floating point value. These in turn are invoked from templates in locale_facets.tcc: num_get<_ChartT, _InIter>::do_get(..., float&) num_get<_ChartT, _InIter>::do_get(..., double&) num_get<_ChartT, _InIter>::do_get(..., long double&) money_get<_ChartT, _InIter>::do_get(..., long double&) locale::facet is used in stream I/O. Impact: Intermittent failures in multi-threaded applications when converting floating point numbers from text to a binary value. More specifically, if the text expresses an out-of-range value (e.g. exponent overflow for a 32-bit float), an incorrect value may be returned rather than setting failbit. -- Summary: c++locale.o thread-unsafe in libstdc++ Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: craig dot lawson at centrify dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #2 from craig dot lawson at centrify dot com 2007-03-10 00:15 --- Seems like that define should come from gcc's "-pthread" option so it applies to all source files. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #4 from craig dot lawson at centrify dot com 2007-03-12 18:26 --- Perhaps there are different degrees of thread safety here. If I write my multi-threaded program such that only one thread does stream I/O with libstdc++, I would expect it to operate safely with respect to the locale issue. But it will not: any other thread which modifies errno (via set_errno) is potential trouble for my stream I/O thread. On the other hand, if __convert_to_v was compiled to use the errno address function, my program would be correct. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug c/31153] New: -Wconversion does not catch return value mismatch
In functions declared to return unsigned int, -Wconversion correctly warns when a constant signed int is returned. But -Wconversion fails to warn when the return value is an identifier with type signed int. Seen in gcc 3.2.3 (Red Hat) and 4.0.1 (Mac OS X) -- Summary: -Wconversion does not catch return value mismatch Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: craig dot lawson at centrify dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31153
[Bug c/31153] -Wconversion does not catch return value mismatch
--- Comment #1 from craig dot lawson at centrify dot com 2007-03-12 18:53 --- Test program (Create a New Attachment is not working for me today): const int i = -1; unsigned int slip_one_by() { return i; } unsigned int caught_me() { return -1; } $ gcc -c unsigned_return.c -Wconversion unsigned_return.c: In function `caught_me': unsigned_return.c:10: warning: negative integer implicitly converted to unsigned type Expected a warning for line 5, too. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31153
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #6 from craig dot lawson at centrify dot com 2007-03-12 19:23 --- > Anyway, what happens in the GNU systems is that errno is a per-thread variable > and the __convert_to_v code has to do nothing special, just safely use it. I agree. The problem is that this is not happening. __convert_to_v is not safely using the per-thread errno. Instead, it is using the global errno. The cause is not the __convert_to_v code but something in an include file or a gcc option which causes the code to be compiled incorrectly. Yet another file in the same library compiled with the same gcc options does access the thread-safe errno correctly. That a discrepancy exists indicates a problem somewhere. The intent of this bug is to call attention to this misuse of errno and the indication of an underlying problem. Thank you for explaining the issues with setlocale. Worse than I thought. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #8 from craig dot lawson at centrify dot com 2007-03-12 20:07 --- Not on Linux: correct. I could give it a try, but I haven't built this library before. If you could point me to a brief how-to, I could give it a try on a Solaris 10 SPARC. Rather than code around it, I would first review the preprocessor output from the two files which access errno. If the compiler options are the same, then problem is somewhere in a header file. And if that's the case, it would be useful to understand the issue. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #10 from craig dot lawson at centrify dot com 2007-03-14 18:13 --- Found it. The problem is that the library is not be ing properly compiled for multi-threaded use, but that by some luck basic_file.cc happened to be compiled that way anyway. c++locale.cc was not so lucky. There are two possible solutions. The solution I believe is best is to compile with the -pthread option. This is what GNU's own documentation recommends for building MT-compatible objects, and is designed to be supported across all platforms. This option defines the appropriate CPP symbol which causes the errno function to be declared rather than the errno global int. I'm not sure where to insert this flag in configure. If you can tell me, I can try it out. The next best solution is to add #include #include to the top of before it includes . These files define the same CPP symbol as -pthread. However, I'm not confident that will do the job on all platforms. Someone who knows better should evaluate this. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug c++/31177] New: make install fails on Solaris 10 SPARC
make install fails with: echo 'SYSTEM_HEADER_DIR="'"`echo /usr/include | sed -e :a -e "s,[^/]*/\.\.\/,," -e ta`"'"' \ > /test/gcc412/test/gcc-4.1.2/usr/local/lib/gcc/sparc-sun-solaris2.10/4.1.2/install-tools/mkheaders.conf /bin/sh: : cannot execute /bin/sh: /]*/../,, -e ta: not found sed: command garbled: s,[ The problem is in install-mkheaders target. Expansion of SYSTEM_HEADER_DIR within double quotes results in mismatched quotes. Shell then tries to evaluate the sed pattern. Fix: File: BUILD-ROOT/host-sparc-sun-solaris2.10/gcc/Makefile (This Makefile was generated. Not sure from where.) Change: SYSTEM_HEADER_DIR = `echo $(NATIVE_SYSTEM_HEADER_DIR) | sed -e :a -e "s,[^/]*/\.\.\/,," -e ta` to: SYSTEM_HEADER_DIR = `echo $(NATIVE_SYSTEM_HEADER_DIR) | sed -e :a -e 's,[^/]*/\.\.\/,,' -e ta` (double quotes to single quotes) -- Summary: make install fails on Solaris 10 SPARC Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: craig dot lawson at centrify dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31177
[Bug target/31177] make install fails on Solaris 10 SPARC
--- Comment #3 from craig dot lawson at centrify dot com 2007-03-14 20:00 --- Yeah... I missed that one. I have bash installed. If bash works, why can't the configure script find it automatically? -- craig dot lawson at centrify dot com changed: What|Removed |Added Status|RESOLVED|VERIFIED http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31177
[Bug target/31177] make install fails on Solaris 10 SPARC
--- Comment #4 from craig dot lawson at centrify dot com 2007-03-14 20:01 --- Yeah... I missed that one. I have bash installed. If bash works, why can't the configure script find it automatically? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31177
[Bug target/31177] make install fails on Solaris 10 SPARC
--- Comment #5 from craig dot lawson at centrify dot com 2007-03-14 20:01 --- (oops. hit "verified" by mistake.) -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31177
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #13 from craig dot lawson at centrify dot com 2007-03-15 02:02 --- (reply to comment #11) Shear luck: Fair enough. I don't claim to understand it all, either, especially how it came to be this way. What appears to be happening on Solaris 10 is that followed by "/usr/include/locale.h" defines the CPP symbols which select the errno function. That happens in the wrong order in c++locale.cc. In that file, moving to the end of the list fixes the problem, too. In fact, moving it below is all that is necessary. And so I thought, and are configuring the compilation environment for threads and they don't have much to be concerned about ... why isn't doing that -- that's what needs it the most! And what is the down side of including files which may select the errno function? The errno function is always safe, even in single-threaded programs. I'm not aware that there's any more to it than this, though I could be wrong. -pthread vs -pthreads: In the 3.x releases which I use, this is the case. It's -pthread on every system except for Solaris where it's -pthreads. Also except on Irix where gcc doesn't recognize the option at all. But 4.1.2 gcc on Solaris (which I just built) accepts either one interchangably. That's progress. Not sure about 4.1.2 Irix. And there are plenty of other platforms that I don't know about. Testing: After several full builds, I began experimenting with the includes and narrowed my test down to this command taken from my build log: BUILD-ROOT/host-sparc-sun-solaris2.10/gcc/xgcc -c c++locale.cc -E | grep __errno If it displays "extern int *___errno();", then the build will produce a multi-threaded object. If not, single-threaded as it does now. (reply to comment #12) Sane set of headers: Yes, I agree with you. Should not be happening. Perhaps it's better to focus on rather than -pthread. Exactly which CPP symbol: On this platform, to select the errno function, /usr/include/errno.h requires defined(_REENTRANT) || defined(_TS_ERRNO) || _POSIX_C_SOURCE - 0 >= 199506L My guess is most likely _REENTRANT or _POSIX_C_SOURCE. -> /usr/include/locale.h -> /usr/include/sys/feature_tests.h, /usr/include/sys/ccompile.h, /usr/include/sys/isa_defs.h, Some of these system header files do testing and setting of _REENTRANT and _POSIX_C_SOURCE, but they're difficult to follow. One frustration I have with CPP output is that #defines are not visible. I can see comments (with -CC), but that's not quite good enough. That's as deep as I've dug at this point. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #16 from craig dot lawson at centrify dot com 2007-03-15 18:15 --- (In reply to comment #15) Tried it. Did not work. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #18 from craig dot lawson at centrify dot com 2007-03-15 18:39 --- (In reply to comment #17) > Why? Don't know. The file and change were included as expected. Without fully understanding how CPP is evaluating these files, we're shooting in the dark. gcc's -E and -CC options provide only a limited view: they show everything except the "#" statements evaluated. Is there a way to see exactly what CPP has evaluated? Either an environment variable, an option, or another tool? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #21 from craig dot lawson at centrify dot com 2007-03-15 19:07 --- (In reply to comment #17) > Why? OK, now I know why. Reason is that os_defines.h is included after errno.h. Here's the include sequence: c++locale.cc /usr/include/errno.h<-- extern int errno <-- _TS_ERRNO -- too late I also now know why basic_file.cc gets the errno function: /usr/include/sys/feature_tests.h defines _POSIX_C_SOURCE to 199506L, and that's what errno.h needs. When compiling c++locale.cc, _POSIX_C_SOURCE is also set to the same value, but it happens after errno.h is processed. Thanks Andrew for -dD. That's a good one. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #23 from craig dot lawson at centrify dot com 2007-03-15 19:26 --- (In reply to comment #22) > Oh yes, you are totally right. The problem is that is one of the very > few c headers not including first. We can easily fix that. Why did not include ? Was this intentional? > Ok, but on other targets I don't think we can trust locale.h to always include > something similar and enable the thread safe errno. I agree. They're all going to be different. But the evidence from basic_file.o indicates that they all do something. > Thus, my preference goes for the plan of adding that define in os_defines.h (+ > adjusting of course). Are you positive about figuring out something > similar to _TS_ERRNO for the other targets? Instead of _TS_ERRNO and equivalent, how about including in ? That appears sufficient for basic_file.o to be compiled correctly, and it appears to work on the platforms I investigated. What do you mean by "are you positive"? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #25 from craig dot lawson at centrify dot com 2007-03-15 20:28 --- (In reply to comment #24) > Oh, that's excellent news, because we have to include first > in anyway... But now you make me curious!!! If you look at > c++config.h > it doesn't appear do much related to this issue Sorry, that news was too excellent. It's not true. The reason I suggested also including in comment #10 was because I found was not enough. I agree that is perhaps a poor choice. I think it needs further investigation as to what would be a good choice. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #27 from craig dot lawson at centrify dot com 2007-03-15 21:17 --- (In reply to comment #26) I understand. I'll collect this information from the systems I have, and then post it here ... -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117
[Bug libstdc++/31117] c++locale.o thread-unsafe in libstdc++
--- Comment #28 from craig dot lawson at centrify dot com 2007-03-22 23:44 --- For HP-UX, SunOS, and Irix: #if !defined(_POSIX_C_SOURCE) # define _POSIX_C_SOURCE 199506L #elif _POSIX_C_SOURCE<199506L # error "Conflict" #endif (why would anyone compile C++ with POSIX < 1995.06?) For AIX, either: #define _THREAD_SAFE or #define _THREAD_SAFE_ERRNO Details: HP-UX 11.00, 11.11, 11.22, 11.23: errno.h: #ifdef _REENTRANT # ifdef _PROTOTYPES extern int *__errno(void); # else extern int *__errno(); # endif ... However, errno.h includes which contains: /* _REENTRANT selects Posix 1c threads unless draft4 selected. * This usage is obsolescent, "-D_POSIX_C_SOURCE=199506" is preferred */ ... #if (_POSIX_C_SOURCE >= 199506) && !defined(_REENTRANT) # define _REENTRANT #endif /* _POSIX_C_SOURCE >= 199506 && !_REENTRANT */ It appears _POSIX_C_SOURCE=199506 is the desired symbol and value, but there will be a conflict if intentionally set to something lower (higher is OK). Confirm using test program: #include int main() { return errno; } Confirmed: -D_POSIX_C_SOURCE=199506 works. SunOS 2.6, 7, 5.8, 5.9, 5.10: errno.h: #if (defined(_REENTRANT) || defined(_TS_ERRNO) || \ _POSIX_C_SOURCE - 0 >= 199506L) && !(defined(lint) || defined(__lint)) Confirmed: -D_POSIX_C_SOURCE=199506 works. AIX 4.3.3, 5.1: errno.h: #include #ifdef _ANSI_C_SOURCE # if defined(_THREAD_SAFE) || defined(_THREAD_SAFE_ERRNO) # define errno (*_Errno()) standards.h: defines _ANSI_C_SOURCE unless overridden by some other model. Confirmed: -D_THREAD_SAFE works. Confirmed: -D_THREAD_SAFE_ERRNO works. AIX 5.2: errno.h: similar to 4.3.3 standards.h: #if defined(_UNIX03) # define _THREAD_SAFE ... #if _XOPEN_SOURCE==600 # define _THREAD_SAFE ... Due to statement ordering in this file, if _POSIX_C_SOURCE==200112L before including this file, then _THREAD_SAFE will be set. Otherwise, this file sets _POSIX_C_SOURCE==200112L and does not set _THREAD_SAFE. Confirmed: -D_THREAD_SAFE works. Confirmed: -D_THREAD_SAFE_ERRNO works. Confirmed: -D_UNIX03 works. Size effect: sets _POSIX_C_SOURCE==200112L Irix 6.5: errno.h: #if defined(_SGI_MP_SOURCE) || (_POSIX_C_SOURCE >= 199506L) \ || (_XOPEN_SOURCE+0 >= 500) extern int *__oserror(void); ... Confirmed: -D_POSIX_C_SOURCE=199506 works. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31117