Created attachment 7402 [details] source file to reproduce the problem the two functions pthread_cond_wait and pthread_cond_timedwait do not suspend the calling thread if the condition variable has a misaligned address. attached find the source code to reproduce the problem as well as a file describing my current software configuration. to compile gcc -g3 -pthread -o cond_ex cond_example.c then run the program and watch the cpu load with top -p <process id> should see the waiter tread continuously running instead of sleeping. to remove the problem compile with gcc -D_ALIGNED -g3 -pthread -o cond_ex cond_example.c the followings are some system information of my linux machine cat /proc/version Linux version 2.6.32-220.7.1.el6.centos.plus.i686 (root@thalix11dev) (gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) ) #1 SMP Mon Oct 21 07:05:28 UTC 2013 rpm -qa | grep glibc glibc-devel-2.12-1.47.i686 glibc-common-2.12-1.47.i686 glibc-2.12-1.47.i686 glibc-debuginfo-2.12-1.47.i686 glibc-headers-2.12-1.47.i686 glibc-utils-2.12-1.47.i686 glibc-debuginfo-common-2.12-1.47.i686 glibc-static-2.12-1.47.i686 cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 15 model : 3 model name : Intel(R) Pentium(R) 4 CPU 2.80GHz stepping : 4 cpu MHz : 2799.930 cache size : 1024 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 5 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe constant_tsc up pebs bts pni dtes64 monitor ds_cpl cid xtpr bogomips : 5586.31 clflush size : 64 cache_alignment : 128 address sizes : 36 bits physical, 32 bits virtual power management: rpm -qa | grep gcc gcc-4.4.6-3.el6.i686 libgcc-4.4.6-3.el6.i686 gcc-c++-4.4.6-3.el6.i686
Don't do that then. Using a misaligned object invokes undefined behaviour.
(In reply to Andreas Schwab from comment #1) > Don't do that then. Using a misaligned object invokes undefined behaviour. you are right, now I'm modified the software. but, as far as I know, in the pthread documentation is no written that the object must be longword aligned. Am I wrong?
> Don't do that then. Using a misaligned object invokes undefined behaviour. From testcase: typedef struct { pthread_mutex_t M; #ifndef _ALIGNED unsigned char c; #endif pthread_cond_t C; } cond_mutex_t; That would exclude using condition variables in structures as undefined behaviour.
You've missed the pragma pack above. In non-packed structures you can obviously include pthread_cond_t just fine.
I think that the pthread documentation should be updated (at least). The best would be to exit from the initializing function pthread_cond_init with an error if the condition variable address is misaligned
I think this bug should be closed as invalid. Using a pointer to a member of a packed structure always results in undefined behavior. This is the case even for things like scanf("%d", &packedstruct.foo). It happens to "work" on x86, but on other systems it will either fault or silently corrupt adjacent members (by ignoring the low bits of the address). It's not glibc's job to fix the application's UB from invalid use of packed attribute/pragma. I've seen and generally agree with the argument that it's nicer for UB to quickly crash than to misbehave in more subtle ways, but to make that behavior consistent, there are hundreds if not thousands of functions which would need to check their argument alignments. Cond vars are not special. Putting such checks all over the place would be impractical; if that level of checking is desired, it belongs in a compiler feature.
BTW I think this general class of bugs should be filed as a bug against GCC: misaligned packed structure members should have the fact that they're misaligned encoded as part of their type, so that applying the address-of operator to them yields a pointer type that's not compatible with the standard pointer type. Then, pthread_cond_wait(&packed_struct.misaligned_cond, ...) would yield a compile-time error due to incompatible pointer types. Likewise, the compile's format string warnings could catch the mismatched pointer type in scanf("%d", &packed_struct.foo).
I think (In reply to Rich Felker from comment #7) > BTW I think this general class of bugs should be filed as a bug against GCC: > misaligned packed structure members should have the fact that they're > misaligned encoded as part of their type, so that applying the address-of > operator to them yields a pointer type that's not compatible with the > standard pointer type. Then, > pthread_cond_wait(&packed_struct.misaligned_cond, ...) would yield a > compile-time error due to incompatible pointer types. Likewise, the > compile's format string warnings could catch the mismatched pointer type in > scanf("%d", &packed_struct.foo). I think this is a good point so I'll try to submit this bug to the GCC guys.
BTW, don't you think that somewhere, in the glibc documentation, should be clearly stated that misaligned object could lead to unpredictable behavior? As far as I know I've never read something like this. If there is, can you just point it out? thanks
This is basic C knowledge that has nothing to do with glibc.
(In reply to Andreas Schwab from comment #10) > This is basic C knowledge that has nothing to do with glibc. can you please (forgiving me for my ignorance) point out some documentation on this matter, then?
Just read the C standard?
(In reply to Jakub Jelinek from comment #12) > Just read the C standard? which paragraph? I mean, if you know it
Or any decent C textbook.
(In reply to Andreas Schwab from comment #14) > Or any decent C textbook. seriously, give me a suggestion. I'm only asking for help, no joke! I've searched the web but I didn't find any clear statement about misaligned variables always leading to unpredictable result. I've only found about performance issues. why can't you just give me some reference instead of fooling me?
6.3.2.3#7
(In reply to Andreas Schwab from comment #16) > 6.3.2.3#7 from the paragraph you mention ----------------------- If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined ----------------------- the problem is: imagine I have to pack my types to save some memory (unfortunately in embedded software this is often the case) and I do not know that the correct alignment of a pthread_cond_t variable is 4 so I, *** by mistake ***, place a pthread_cond_t variable at a wrong address (considering its correct alignment) what is my chance to catch the bug? where is written that a pthread_cond_t variable must be 4 byte aligned? I'm just talking about this, a way to avoid or to earlier detect such kind of errors
On Wed, Feb 12, 2014 at 10:09:40AM +0000, vinxxe at gmail dot com wrote: > seriously, give me a suggestion. I'm only asking for help, no joke! > I've searched the web but I didn't find any clear statement about misaligned > variables always leading to unpredictable result. I've only found about > performance issues. why can't you just give me some reference instead of > fooling me? The C standard simply does not allow misaligned objects to even come into existence. The only way you can get them is by performing illegal pointer arithmetic/casts/aliasing violations or by using nasty nonstandard compiler-specific features like __attribute__ or #pragma pack. The latter (these compilers) is where the documentation belongs that you cannot take the address of a misaligned object and pass it to a function expecting a pointer to that type. At present I don't think they are documenting this correctly. This is why I suggested filing a bug report against GCC to tag the type so that attempting to pass it is a compile-time error.
On Wed, Feb 12, 2014 at 11:34:49AM +0000, vinxxe at gmail dot com wrote: > the problem is: imagine I have to pack my types to save some memory This is a fallacy. Unless you have a very large number of objects, the amount of supporting code bloat to access misaligned objects is orders of magnitude larger than what you save. Pthread synchronization objects are also sufficiently large in themselves that they're going to dominate any "waste" from padding. Moreover, if you just order your struct members correctly (approximately: from largest to smallest) you'll ensure that there is little or no padding. > where is written that a pthread_cond_t variable must be 4 byte aligned? Nowhere. On a C11 compiler, _Alignof could tell you this, but otherwise the alignment requirement is not a documented aspect of the interface because it can vary by target and you're supposed to be relying on the compiler to align it correctly. > I'm just talking about this, a way to avoid or to earlier detect such kind of > errors Unless you can prove the member in question is aligned, you can simply never apply the & operator to any member of a packed structure. The best way to avoid doing this is not using packed structures at all.
I already agreed with your point. As a matter of fact I removed the bug and submitted the question to the gcc guys. (In reply to Rich Felker from comment #18) > On Wed, Feb 12, 2014 at 10:09:40AM +0000, vinxxe at gmail dot com wrote: > > seriously, give me a suggestion. I'm only asking for help, no joke! > > I've searched the web but I didn't find any clear statement about misaligned > > variables always leading to unpredictable result. I've only found about > > performance issues. why can't you just give me some reference instead of > > fooling me? > > The C standard simply does not allow misaligned objects to even come > into existence. The only way you can get them is by performing illegal > pointer arithmetic/casts/aliasing violations or by using nasty > nonstandard compiler-specific features like __attribute__ or #pragma > pack. The latter (these compilers) is where the documentation belongs > that you cannot take the address of a misaligned object and pass it to > a function expecting a pointer to that type. At present I don't think > they are documenting this correctly. This is why I suggested filing a > bug report against GCC to tag the type so that attempting to pass it > is a compile-time error.
I agree with you, again. Unfortunately things are not so easy. I never wrote the incriminate code. The code was written by someone on a very old hw with an Mx rtos. Then someone else ported this software under Linux. Then they gave to me the work of making things work (because as you can easily imagine nothing worked). And in the software the pragma pack is written in one header file included by every source file, so you cannot say, at first sight, that the compiler is packing everything. This is the very nasty story. I never had such kind of problem before because, like you suggest, I never use the nasty compiler tools. BTW thank you again for your time (In reply to Rich Felker from comment #19) > On Wed, Feb 12, 2014 at 11:34:49AM +0000, vinxxe at gmail dot com wrote: > > the problem is: imagine I have to pack my types to save some memory > > This is a fallacy. Unless you have a very large number of objects, the > amount of supporting code bloat to access misaligned objects is orders > of magnitude larger than what you save. Pthread synchronization > objects are also sufficiently large in themselves that they're going > to dominate any "waste" from padding. Moreover, if you just order your > struct members correctly (approximately: from largest to smallest) > you'll ensure that there is little or no padding. > > > where is written that a pthread_cond_t variable must be 4 byte aligned? > > Nowhere. On a C11 compiler, _Alignof could tell you this, but > otherwise the alignment requirement is not a documented aspect of the > interface because it can vary by target and you're supposed to be > relying on the compiler to align it correctly. > > > I'm just talking about this, a way to avoid or to earlier detect such kind of > > errors > > Unless you can prove the member in question is aligned, you can simply > never apply the & operator to any member of a packed structure. The > best way to avoid doing this is not using packed structures at all.