From: Paul Eggert Date: Mon, 14 Dec 2020 19:38:18 +0000 (-0800) Subject: free: preserve errno X-Git-Tag: v1.0~3360 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=665f174a1eab75d55ef759b6424ce5b678f496df;p=gnulib.git free: preserve errno * lib/free.c (rpl_free): Preserve errno. Check for null only if CANNOT_FREE_NULL is defined, as an optimization for POSIX 2008 platforms that do not preserve errno. * m4/free.m4 (gl_FUNC_FREE): Check whether free preserves errno. Also, define CANNOT_FREE_NULL if free cannot free NULL. * modules/free (configure.ac): Also replace 'free' if it does not preserve errno. --- diff --git a/ChangeLog b/ChangeLog index 445e2c0744..e97d82aa6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2020-12-17 Paul Eggert + free: preserve errno + * lib/free.c (rpl_free): Preserve errno. Check for null only if + CANNOT_FREE_NULL is defined, as an optimization for POSIX 2008 + platforms that do not preserve errno. + * m4/free.m4 (gl_FUNC_FREE): Check whether free preserves errno. + Also, define CANNOT_FREE_NULL if free cannot free NULL. + * modules/free (configure.ac): Also replace 'free' if + it does not preserve errno. + idx: simplify IDX_MAX, remove IDX_WIDTH * lib/idx.h (IDX_MAX): Simplify by removing obsolete reference to UNSIGNED_IDX_T. diff --git a/lib/free.c b/lib/free.c index 50a300ffa6..843ce4816b 100644 --- a/lib/free.c +++ b/lib/free.c @@ -22,9 +22,17 @@ #include +#include + void rpl_free (void *p) { - if (p) - free (p); +#ifdef CANNOT_FREE_NULL + if (!p) + return; +#endif + + int err = errno; + free (p); + errno = err; } diff --git a/m4/free.m4 b/m4/free.m4 index a62214cd12..62daa8ecc3 100644 --- a/m4/free.m4 +++ b/m4/free.m4 @@ -35,10 +35,43 @@ AC_DEFUN([gl_FUNC_FREE], esac ]) + dnl In the next release of POSIX, free must preserve errno. + dnl https://www.austingroupbugs.net/view.php?id=385 + dnl https://sourceware.org/bugzilla/show_bug.cgi?id=17924 + dnl For now, assume implementations other than glibc do not preserve errno + dnl unless they set _POSIX_VERSION to the next release number, + dnl whatever that happens to be. + AC_CACHE_CHECK([whether free is known to preserve errno], + [gl_cv_func_free_preserves_errno], + [case $host_os in + *-gnu* | gnu*) + gl_cv_func_free_preserves_errno=yes;; + *) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[#if _POSIX_VERSION <= 200809 + #error "'free' is not known to preserve errno" + #endif + ]])], + [gl_cv_func_free_preserves_errno=yes], + [gl_cv_func_free_preserves_errno=no]);; + esac + ]) + if test $gl_cv_func_free = no; then + AC_DEFINE([CANNOT_FREE_NULL], [1], + [Define to 1 if free (NULL) does not work.]) + fi + + case $gl_cv_func_free,$gl_cv_func_free_preserves_errno in + *yes,*yes) ;; + *) AC_DEFINE([free], [rpl_free], [Define to rpl_free if the replacement function should be used.]) - fi + ;; + esac ]) # Prerequisites of lib/free.c. diff --git a/modules/free b/modules/free index ec91f8889d..ea2509821f 100644 --- a/modules/free +++ b/modules/free @@ -1,8 +1,5 @@ Description: -Work around incompatibility on older systems where free (NULL) fails. - -Notice: -This module is obsolete. +Work around systems where free sets errno or free (NULL) fails. Files: lib/free.c @@ -12,10 +9,13 @@ Depends-on: configure.ac: gl_FUNC_FREE -if test $gl_cv_func_free = no; then +case $gl_cv_func_free,$gl_cv_func_free_errno in + *yes,*yes) ;; + *) AC_LIBOBJ([free]) gl_PREREQ_FREE -fi + ;; +esac Makefile.am: