This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch releases/13.1
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/releases/13.1 by this push:
new 248e0220a4f binfmt: Update the TLS pid when exec() swaps the pids.
248e0220a4f is described below
commit 248e0220a4f303c8c394672c0b443e752c7817a3
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Oct 6 18:15:38 2026 +0200
binfmt: Update the TLS pid when exec() swaps the pids.
exec() swaps the pids of the caller and the new task, so that the new
program keeps the pid of the caller. exec_swap() changes tcb->pid and
group->tg_pid. But getpid() and gettid() read the copies in TLS,
tg_info->ta_pid and tl_tid, and exec_swap() does not change them. So
getpid() in the new program returns the pid that the caller has now, and
kill(getpid(), sig) sends the signal to the caller.
Make exec_swap() update both copies for both tasks. The address
environment of the new task is current in exec_swap(). The TLS of the
caller is in the address environment of the caller, so exec_swap()
selects that environment for the update of the caller.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
binfmt/binfmt_execmodule.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c
index 867091c61a0..d27218a9233 100644
--- a/binfmt/binfmt_execmodule.c
+++ b/binfmt/binfmt_execmodule.c
@@ -39,6 +39,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/kmalloc.h>
#include <nuttx/sched.h>
+#include <nuttx/tls.h>
#include <sched/sched.h>
#include <task/spawn.h>
#include <nuttx/spawn.h>
@@ -78,6 +79,10 @@ static void exec_swap(FAR struct tcb_s *ptcb, FAR struct
tcb_s *chtcb)
int chndx;
pid_t pid;
irqstate_t flags;
+ FAR struct tls_info_s *info;
+#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
+ FAR struct addrenv_s *oldenv;
+#endif
#ifdef CONFIG_SCHED_HAVE_PARENT
# ifdef CONFIG_SCHED_CHILD_STATUS
FAR struct child_status_s *tg_children;
@@ -131,6 +136,27 @@ static void exec_swap(FAR struct tcb_s *ptcb, FAR struct
tcb_s *chtcb)
#endif
leave_critical_section(flags);
+
+ /* getpid() and gettid() read copies of the pids in TLS. The address
+ * environment of the child is current here, and the TLS of the caller
+ * is in its own.
+ */
+
+ info = (FAR struct tls_info_s *)chtcb->stack_alloc_ptr;
+ info->tl_tid = chtcb->pid;
+ chtcb->group->tg_info->ta_pid = chtcb->group->tg_pid;
+
+#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
+ addrenv_select(ptcb->addrenv_own, &oldenv);
+#endif
+
+ info = (FAR struct tls_info_s *)ptcb->stack_alloc_ptr;
+ info->tl_tid = ptcb->pid;
+ ptcb->group->tg_info->ta_pid = ptcb->group->tg_pid;
+
+#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
+ addrenv_restore(oldenv);
+#endif
}
/****************************************************************************