[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: free-posix: New module, renamed from 'free'
From: |
Bruno Haible |
Subject: |
Re: free-posix: New module, renamed from 'free' |
Date: |
Sat, 19 Dec 2020 20:20:18 +0100 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-197-generic; KDE/5.18.0; x86_64; ; ) |
Paul Eggert wrote:
> > I'm adding a unit test for the "free() preserves errno" feature.
>
> Thanks. Unfortunately the test fails on Ubuntu 20.10 (and I assume on other
> GNU/Linux hosts). So I installed the attached patch to port the free-posix
> module to GNU/Linux (!).
Thanks; I intended to propose this change and ask you whether it's OK with you.
I noted the test failure on:
Linux 2.4.22 / glibc 2.3.2 (Fedora 1)
Linux 4.4 / glibc 2.23 (Ubuntu 16.04)
Linux 4.18 / glibc 2.28 (CentOS 8)
Linux 5.8 / glibc 2.32 (Ubuntu 20.10)
as well as
Linux 5.4.43 / musl libc 1.1.24 (Alpine Linux 3.12)
> Perhaps someday we can move the test to m4/free.m4 with AC_RUN_IFELSE, but
> there's no rush if the problem is ubiquitous.
I don't think we will ever have a reliable AC_RUN_IFELSE test for this
feature, because to get free() on the failure path, often you need to put
the process into a near-out-of-memory state; on Linux this might kill other
processes, whereas on other OSes it may crash the entire machine.
Such a guarantee can only be given through documentation or by a code
inspection.
Also, I don't trust _POSIX_VERSION to be the right indicator, because we
have seen so often that a system has only some traits of a standard, but
not all. Even the glibc people do this, cf.
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c70824b9a4645c0ecd049da8cfdb2c28ae7ada23
Inspecting the various implementations of free() — in the source code or
with strace / truss — , here are my findings:
* OpenBSD is good since version 4.5, since they explicitly save errno.
See
https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/malloc.c.diff?r1=1.100&r2=1.101&f=h
* Solaris (10, 11, OpenIndiana) is good, since malloc() only ever invokes
brk(), not mmap(). Therefore free() does not make system calls.
* In various other BSDs, free() invokes munmap() without protecting errno.
* In glibc, there's also another risky code path: an experimental feature,
where the first free() in a thread invokes malloc(). It should be possible
to do a malloc() in the main thread, then exhaust nearly all of the ulimit,
create a thread, and call free() of the block in this thread.
* Also, in glibc, the user can install their custom free() handler. As long
as it is not documented that this free() handler must preserve errno, glibc
free() cannot be considered safe either.
2020-12-19 Bruno Haible <bruno@clisp.org>
free-posix: Assume future POSIX compliance only on OpenBSD and Solaris.
* m4/free.m4 (gl_FUNC_FREE): Guess yes only on OpenBSD and Solaris.
Don't trust _POSIX_VERSION for this test.
diff --git a/m4/free.m4 b/m4/free.m4
index e7a7203..53df743 100644
--- a/m4/free.m4
+++ b/m4/free.m4
@@ -1,33 +1,43 @@
-# free.m4 serial 3
+# free.m4 serial 4
# Copyright (C) 2003-2005, 2009-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# Written by Paul Eggert.
+# Written by Paul Eggert and Bruno Haible.
AC_DEFUN([gl_FUNC_FREE],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST])
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.
+ dnl So far, we know of two platforms that do this:
+ dnl * OpenBSD >= 4.5, thanks to this commit:
+ dnl
<https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/malloc.c.diff?r1=1.100&r2=1.101&f=h>
+ dnl * Solaris, because its malloc() implementation is based on brk(),
+ dnl not mmap(); hence its free() implementation makes no system calls.
+ dnl For other platforms, you can only be sure if they state it in their
+ dnl documentation, or by code inspection of the free() implementation in
libc.
AC_CACHE_CHECK([whether free is known to preserve errno],
[gl_cv_func_free_preserves_errno],
- [AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM(
- [[#include <unistd.h>
- ]],
- [[#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])
+ [case "$host_os" in
+ # Say yes only if we know it.
+ openbsd* | solaris*)
+ gl_cv_func_free_preserves_errno=yes
+ ;;
+ # It's no on Linux, for implementations that call munmap(), due to
+ # /proc/sys/vm/max_map_count.
+ linux*)
+ gl_cv_func_free_preserves_errno=no
+ ;;
+ # If we don't know, obey --enable-cross-guesses.
+ *)
+ gl_cv_func_free_preserves_errno="$gl_cross_guess_normal"
+ ;;
+ esac
])
case $gl_cv_func_free_preserves_errno in
- [PATCH] free: preserve errno, Paul Eggert, 2020/12/17
- Re: [PATCH] free: preserve errno, Pádraig Brady, 2020/12/17
- free: Remove support for obsolete platforms, Bruno Haible, 2020/12/18
- free-posix: New module, renamed from 'free', Bruno Haible, 2020/12/18
- Re: free-posix: New module, renamed from 'free', Bruno Haible, 2020/12/19
- Re: free-posix: New module, renamed from 'free', Paul Eggert, 2020/12/19
- Re: free-posix: New module, renamed from 'free',
Bruno Haible <=
- Re: free-posix: New module, renamed from 'free', Paul Eggert, 2020/12/20
- Re: free-posix: New module, renamed from 'free', Bruno Haible, 2020/12/19
- Re: free-posix: New module, renamed from 'free', Paul Eggert, 2020/12/19