From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 875343948A8D for ; Tue, 1 Jun 2021 14:18:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 875343948A8D Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-528-G3WbHpcDMJyKXYNcY6kW5g-1; Tue, 01 Jun 2021 10:18:17 -0400 X-MC-Unique: G3WbHpcDMJyKXYNcY6kW5g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6C3A21858EC0; Tue, 1 Jun 2021 14:18:16 +0000 (UTC) Received: from oldenburg.str.redhat.com (ovpn-113-228.ams2.redhat.com [10.36.113.228]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5F5888FB66; Tue, 1 Jun 2021 14:18:15 +0000 (UTC) From: Florian Weimer To: Adhemerval Zanella Cc: Libc-alpha , hpa@zytor.com Subject: Re: RFC: pthread pid accessor (BZ# 27880) References: <6d79a213-0df2-be8e-3596-e010f366a34f@linaro.org> <87zgwa979l.fsf@oldenburg.str.redhat.com> Date: Tue, 01 Jun 2021 16:18:13 +0200 In-Reply-To: (Adhemerval Zanella's message of "Tue, 1 Jun 2021 11:09:51 -0300") Message-ID: <87y2bt4qje.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Jun 2021 14:18:20 -0000 * Adhemerval Zanella: > On 31/05/2021 13:51, Florian Weimer wrote: >> * Adhemerval Zanella: >> >>> It seems that this is trickier than it seems, some issues we might consider >>> first: >>> >>> 1. What should we do with detached threads? As for pthread_kill, issuing >>> a pthread_gettid_np might use an invalid handler (since the pthread_t >>> identifier might be reused). This only solution I have is to define >>> it as undefined behavior, this is not great but to proper support it >>> would incur to keep tracking or all possible pthread_t identifiers >>> (we already keep the glibc provided stacks, dl_stack_cache, so it >>> would be a matter to include the user provided one in the list as >>> special entries). >> >> Detached threads are fine as long as the thread is still running. This >> is something the application can ensure using synchronization. >> >> There are other interfaces with this property, including pthread_kill. > > Afaik pthread_kill detaches created threads or thread that call > pthread_detach are not really defined (the thread ID lifetime ends > when detached is issued). We even have a bug report for this, BZ > #19193. Bug 19193 is about joinable threads that have exited, not detached threads. > But currently calling pthread_kill is already undefined: it accesses > the internal tid file without any extra check. Even using the > INVALID_NOT_TERMINATED_TD_P/INVALID_TD_P won't really improve thing, since > might still access invalid memory if the thread cache was empty and the > resulted 'struct thread' was deallocated. But that's an implementation bug, not an application bug. INVALID_NOT_TERMINATED_TD_P needs synchronization (possibly blocking the thread from exiting) to be correct. >>> 3. How do we handle the concurrent access between pthread_join and >>> pthread_gettid_np? Once a pthread_join is issued, the pthread_t >>> identifier might be reused and accessing it should be >>> invalid. pthread_join first synchronizes using 'joinid' to avoid >>> concurrent pthread_join and then wait the kernel signal on 'tid' >>> that the thread has finished. The straightforward >>> 'pthread_gettid_np' implementation would do a atomic load on tid, >>> however it might read a transient value between pthread_join >>> 'joinid' setup and the futex wait. I am not sure how to handle it >>> correctly. >> >> The application must ensure through synchronization that the lifetime of >> the thread handle has not ended yet. Concurrent calls with pthread_join >> is fine as long as the thread has not exited yet (same as for >> pthread_kill). >> >> The question is what we should do after thread exit, but with a joinable >> thread. I think for that we should return the original TID the kernel >> assigned (even though it could not be reused). That would strongly >> discourage the unsafe probing behavior because the function cannot be >> used to probe if the thread is still running. > > Do you mean between the thread cancel/exit and kernel reset the struct > thread 'tid' field? The main problem is the thread might be detached > between, that's why pthread_join synchronizes first using the 'joinid' > field. If the thread is detached and has exited, then the lifetime of its handle ends, so this isn't a problem for the new interface (or pthread_kill). My question was about a joinable thread which has exited but which has not been joined yet. We could return the original TID in this case, and there wouldn't any possible for races in this case in this interface because that TID does not change. It then becomes a matter of what you do with the TID. If you only use it for logging, than that is fine. >>> Also, MacOSX signature is: >>> >>> int pthread_gettid_np (pthread_t thread, uint64_t *thread_id) >>> >>> And it returns the current thread identification if THREAD is NULL, returns >>> ESRCH for invalid handle (the 1. and 2. issue below), and also consults >>> the kernel if the identifier can no be obtained. >> >> Macos calls the interface pthread_threadid_np, actually. It looks as if >> it returns a truly unique number that isn't reused within the process or >> system. A Linux TID wouldn't be like that, so I think we should call >> the interface something else. > > Fair enough, bionic has > > pid_t pthread_gettid_np(pthread_t t) > > So I think we might be an option. It basically returns the underlying > kernel process identifier, no extra guarantee as done by MacOSX > implementation. Yes, I would prefer that. Does Bionic return the TID from the resettable TCB field, or a copy? Thanks, Florian