view modules/stdlib @ 14338:d9460671313e

stdlib: support non-GCC __attribute__ Fix a serious and tricky problem encountered when attempting to add the getloadavg module to Emacs. Emacs worked fine on RHEL 5.5, but it crashed due to memory corruption on Solaris 10 with Sun C 5.11. Emacs normally ORs 3-bit tags into their low-order bits that are otherwise zero. This tagging is optional inside Emacs but is preferred and is used when __attribute__ ((__aligned (8))) works, as it does with both recent-enough GCC and with Sun C 5.11. However, Sun C 5.11 is not GCC and does not #define __GNUC__ and __GNUC_MINOR__. When I added the getloadavg module to Emacs, it brought in stdlib.in.h, which contained this fragment: #ifndef __attribute__ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) # define __attribute__(Spec) /* empty */ # endif #endif When files that include <stdlib.h> were compiled with Sun C 5.11, the above code disabled __attribute__ ((__aligned (8))), which caused variables to not be properly aligned, which eventually led to the pointer corruption mentioned above. (This was a bit hard to diagnose, unfortunately.) Several "#define __attribute__(X) /* empty */" code snippets need to be eradicated from Gnulib to work with non-GCC compilers that support __attribute__. The Autoconf way to do this is to test for each kind of attribute that we want support for, and selectively enable that in source code. Fix this problem just for stdlib.h, by adding a test for the __noreturn__ attribute, and change stdlib.in.h to use that test when needed. This technique can be easily generalized to the other *.in.h files and attributes, and a similar technique can be used for *.h and *.c files. This patch is enough to solve the problem for Emacs + getloadavg, and I thought I'd publish it for feedback before undertaking further, similar fixes in other modules. This patch does not arrange to #define HAVE_ATTRIBUTE_NORETURN because it's not needed for stdlib.h. It merely substitutes the value directly into stdlib.h. We may well need to #define it, or similar symbols, for other modules, but it's nice to also have an option to not #define it for applications like Emacs that do not need it. * lib/stdlib.in.h (__attribute__): Do not #define. (_GL_ATTRIBUTE_NORETURN): New macro, which in stdlib.h needs to be defined only if the _Exit module is also used. * m4/_Exit.m4 (gl_FUNC__EXIT): Require gl_ATTRIBUTE_NORETURN. * m4/stdlib_h.m4 (gl_STDLIB_H_DEFAULTS): Subst HAVE_ATTRIBUTE_NORETURN and default it to 1, its value on GNU platforms. * modules/_Exit (Files): Add m4/attribute.m4. * modules/stdlib (Makefile.am): Substitute HAVE_ATTRIBUTE_NORETURN. * m4/attribute.m4: New file.
author Paul Eggert <eggert@cs.ucla.edu>
date Sat, 12 Feb 2011 15:33:16 -0800
parents 6f2788453d27
children b8a7de52bf47
line wrap: on
line source

Description:
A GNU-like <stdlib.h>.

Files:
lib/stdlib.in.h
m4/stdlib_h.m4

Depends-on:
arg-nonnull
c++defs
include_next
stddef
unistd
warn-on-use

configure.ac:
gl_STDLIB_H

Makefile.am:
BUILT_SOURCES += stdlib.h

# We need the following in order to create <stdlib.h> when the system
# doesn't have one that works with the given compiler.
stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
	$(AM_V_GEN)rm -f $@-t $@ && \
	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
	  sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
	      -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \
	      -e 's|@''GNULIB__EXIT''@|$(GNULIB__EXIT)|g' \
	      -e 's|@''GNULIB_ATOLL''@|$(GNULIB_ATOLL)|g' \
	      -e 's|@''GNULIB_CALLOC_POSIX''@|$(GNULIB_CALLOC_POSIX)|g' \
	      -e 's|@''GNULIB_CANONICALIZE_FILE_NAME''@|$(GNULIB_CANONICALIZE_FILE_NAME)|g' \
	      -e 's|@''GNULIB_GETLOADAVG''@|$(GNULIB_GETLOADAVG)|g' \
	      -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \
	      -e 's|@''GNULIB_GRANTPT''@|$(GNULIB_GRANTPT)|g' \
	      -e 's|@''GNULIB_MALLOC_POSIX''@|$(GNULIB_MALLOC_POSIX)|g' \
	      -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \
	      -e 's|@''GNULIB_MKOSTEMP''@|$(GNULIB_MKOSTEMP)|g' \
	      -e 's|@''GNULIB_MKOSTEMPS''@|$(GNULIB_MKOSTEMPS)|g' \
	      -e 's|@''GNULIB_MKSTEMP''@|$(GNULIB_MKSTEMP)|g' \
	      -e 's|@''GNULIB_MKSTEMPS''@|$(GNULIB_MKSTEMPS)|g' \
	      -e 's|@''GNULIB_PTSNAME''@|$(GNULIB_PTSNAME)|g' \
	      -e 's|@''GNULIB_PUTENV''@|$(GNULIB_PUTENV)|g' \
	      -e 's|@''GNULIB_RANDOM_R''@|$(GNULIB_RANDOM_R)|g' \
	      -e 's|@''GNULIB_REALLOC_POSIX''@|$(GNULIB_REALLOC_POSIX)|g' \
	      -e 's|@''GNULIB_REALPATH''@|$(GNULIB_REALPATH)|g' \
	      -e 's|@''GNULIB_RPMATCH''@|$(GNULIB_RPMATCH)|g' \
	      -e 's|@''GNULIB_SETENV''@|$(GNULIB_SETENV)|g' \
	      -e 's|@''GNULIB_STRTOD''@|$(GNULIB_STRTOD)|g' \
	      -e 's|@''GNULIB_STRTOLL''@|$(GNULIB_STRTOLL)|g' \
	      -e 's|@''GNULIB_STRTOULL''@|$(GNULIB_STRTOULL)|g' \
	      -e 's|@''GNULIB_SYSTEM_POSIX''@|$(GNULIB_SYSTEM_POSIX)|g' \
	      -e 's|@''GNULIB_UNLOCKPT''@|$(GNULIB_UNLOCKPT)|g' \
	      -e 's|@''GNULIB_UNSETENV''@|$(GNULIB_UNSETENV)|g' \
	      < $(srcdir)/stdlib.in.h | \
	  sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
	      -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
	      -e 's|@''HAVE_ATTRIBUTE_NORETURN''@|$(HAVE_ATTRIBUTE_NORETURN)|g' \
	      -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \
	      -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
	      -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
	      -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
	      -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \
	      -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \
	      -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \
	      -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \
	      -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \
	      -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \
	      -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \
	      -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \
	      -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \
	      -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \
	      -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \
	      -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
	      -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
	      -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
	      -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
	      -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
	      -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \
	      -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
	      -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
	      -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
	      -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
	      -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
	      -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
	      -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
	      -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \
	      -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
	      -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
	      -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
	} > $@-t && \
	mv $@-t $@
MOSTLYCLEANFILES += stdlib.h stdlib.h-t

Include:
<stdlib.h>

License:
LGPLv2+

Maintainer:
all