From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 97503 invoked by alias); 10 Jun 2019 11:48:58 -0000 Mailing-List: contact libc-help-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Post: List-Help: , Sender: libc-help-owner@sourceware.org Received: (qmail 97493 invoked by uid 89); 10 Jun 2019 11:48:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-8.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=H*p:D*org, happening X-HELO: mail-vs1-f68.google.com Received: from mail-vs1-f68.google.com (HELO mail-vs1-f68.google.com) (209.85.217.68) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jun 2019 11:48:56 +0000 Received: by mail-vs1-f68.google.com with SMTP id l125so5079147vsl.13 for ; Mon, 10 Jun 2019 04:48:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=to:references:from:openpgp:autocrypt:subject:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=rGa8/HIjTTCBE4rO1gFqp/yrEMKwAvhhV6Ans6vRpyQ=; b=V5buqBiQzxPHKiaTbLz8emj7V3VL9pywL0gwv80nrrX2A3960LyeolErFFdiOx9vGb UJCYE6i91Z5BDSF4grM5S4gCsbqkaYsQCalJX3686MjkUt6iaDG/zVQVyUoHlQynjgVS uAMVVs8cLZtZVkoKAEY9TwVtPl13o9dZw15ZviSc79ytXPJ/chCgPEMljsaLfRbuO7OQ FQk07yfI2ZvjEiI3pZXZ6mjd7w0DCjEc55sGzk88s8qJF+wNZxerzlM95WcUvQjvtqRL MeTTawF2pcXdm5fIHpx4V8rjJEG+yPctCEuhiDJCRP7ZCER4tROUzc74tHjBeltnaDEv +x9A== Return-Path: Received: from [192.168.1.132] ([177.194.125.152]) by smtp.googlemail.com with ESMTPSA id b18sm2683430uae.14.2019.06.10.04.48.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Jun 2019 04:48:53 -0700 (PDT) To: libc-help@sourceware.org References: <87blzypg5j.fsf@mid.deneb.enyo.de> <0a7c2435-43f8-8dfb-83ab-22ceff7ca51c@mulle-kybernetik.com> From: Adhemerval Zanella Openpgp: preference=signencrypt Subject: Re: Problem with atexit and _dl_fini Message-ID: Date: Mon, 10 Jun 2019 11:48:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2019-06/txt/msg00006.txt.bz2 On 09/06/2019 17:59, Nat! wrote: > Another datapoint to support my claim that _dl-fini breaks atexit. This time its very easy to reproduce ;) > > Here 's the README.md from the Github Repo https://github.com/mulle-nat/atexit-breakage-linux > > > ``` > > # Shows another breakage involving `atexit` on linux > > Here the `atexit` callback is invoked mistakenly multiple times. This 'example' does not really show the issue because ldd script issues the loader multiple times, see below. You can check exactly what ldd is doing by calling with sh -x. I will try to use your instruction to run on docker to see what exactly is happening in your environment. > > ## Build > > Build with [mulle-make](//github.com/mulle-sde/mulle-make) or alternatively : > > ``` > ( >    mkdir build && >    cd build && >    cmake .. && >    make > ) > ``` > > ## Run > > Use `ldd` to trigger the misbehaviour: > > ``` > LD_PRELOAD="${PWD}/build/libld-preload.so" ldd ./build/main > ``` > > ## Output > > ``` > load > unload First and second time is done on: 158 dummy=`$rtld 2>&1` 159 if test $? = 127; then 160 verify_out=`${rtld} --verify "$file"` 161 ret=$? Where the rtld list is, for x86_64, /lib/ld-linux.so.2 and /lib64/ld-linux-x86-64.so.2 > unload > unload This time is done at: 176 0|2) 177 try_trace "$RTLD" "$file" || result=1 178 ;; 179 *) Where is call the loader as eval LD_TRACE_LOADED_OBJECTS=1 LD_WARN= LD_BIND_NOW= 'LD_LIBRARY_VERSION=$verify_out' LD_VERBOSE= '"$@"' With same rtld list as before. >    linux-vdso.so.1 (0x00007ffd2b2bd000) >    /home/src/srcO/mulle-core/mulle-testallocator/research/ld-preload/build/libld-preload.so (0x00007f83853c1000) >    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f838518c000) >    /lib64/ld-linux-x86-64.so.2 (0x00007f83853cd000) > unload > unload > ``` > > > Ciao >    Nat! > > > On 19.05.19 21:37, Nat! wrote: >> >> On 19.05.19 18:23, Florian Weimer wrote: >>> * Nat!: >>> >>>> So my problem is, that I observe that my atexit calls are not executed >>>> in the correct order. >>>> >>>> i.e. atexit( a); atexit( b);  should result in b(), a() being called in >>>> that order. To quote the man page, >>>> >>>> "the registered functions are invoked in reverse order". >>>> >>>> >>>> When I register with `atexit` I can see my functions being added >>>> properly within `__internal_atexit` in the >>>> >>>> correct order. Finally after my functions, the elf-loader ? also adds >>>> itself there. So it is being called first by >>>> >>>> `__run_exit_handlers`. >>>> >>>> >>>> Then comes the part where it goes wrong. I registered my two function >>>> with `__internal_atexit`, but for some reason >>>> >>>> `_dl_fini` is calling `__cxa_finalize` and that is calling the wrong >>>> function first. >>> When atexit is called from a DSO, glibc calls the registered function >>> before the DSO is unloaded.  This choice was made because after >>> unloading, the function pointer becomes invalid. >>> >>> I haven't checked, but I suspect atexit still works this way even if >>> it doesn't have to (because the DSO is never unloaded). >>> >> >> I understand, but the behavior is wrong :) The C standard (or the C++ standard for this matter) http://www.cplusplus.com/reference/cstdlib/atexit/ states that >> >> >> ``` >> >> If more than one atexit function has been specified by different calls to this function, they are all executed in reverse order as a stack (i.e. the last function specified is the first to be executed at exit). >> >> ``` >> >> I think its been shown that glibc can violate this C standard, so for me the argument would be over here already. That one should unwind in the reverse order is, I assume, not a interesting discussion topic. Currently atexit as a reliable mechanism is broken. >> >> >> But I also don't think the way this is currently handled in glibc, can't be of much use to anyone. >> >> Case 1: a regular exe linked with shared libraries, nothing gets unloaded at exit, so what's the point ? >> >> Case 2: someone manually unloads a shared library, that contains atexit code. The bug is either using `atexit` for a shared library that gets unloaded, or unloading a shared library that contains atexit code. But it's not really glibcs business IMO. >> >> Case 3: some automatism unloads shared libraries. Then the automatism should check if atexit code is affected and not unload, because the shared library is still clearly needed. It's a bug in the automatism. >> >> If one was hellbent on trying to support atexit for unloading shared libraries, an atexit contained in a shared library should up the reference count of the shared library during the atexit call and decrement after the callback has executed. >> >> Ciao >> >>    Nat! >> >>