このコードがコード16で終了するのはなぜですか?

このコードがコード16で終了するのはなぜですか?

スレッドを生成するためにclone()システムコールを使用しようとしています。ただし、プログラムはt2_thread()関数から返されると、それ自体が終了します。なぜこのような問題が発生しますか?私は何を見逃していますか?

#define _GNU_SOURCE
#include<sys/syscall.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<sched.h>

int t2_thread(void *arg)
{
        printf("Thread 2 (%ld)\n",syscall(SYS_gettid));
        return;
}
int main(int argc, char **argv)
{
        const size_t STCK_SZ = 65536;
        char *stck;
        int flags;
        stck = malloc(STCK_SZ);
        if(stck == NULL)
        {
                perror("malloc");
                exit(EXIT_FAILURE);
        }
        flags = CLONE_SIGHAND |CLONE_FS |CLONE_VM |CLONE_FILES | CLONE_THREAD;
        if(clone(t2_thread, stck + STCK_SZ, flags, NULL)==-1)
        {
                perror("clone");
                exit(EXIT_FAILURE);
        }

        printf("Thread 1 (%ld)\n",syscall(SYS_gettid));

        for(;;)
        {
                printf("T1\n");
                sleep(1);
        }
        exit(EXIT_SUCCESS);
}

ちなみに、このプログラムの出力は次のようになります。

Thread 1 (8963)
T1
Thread 2 (8964)

$echo $?
16

forループを無限に実行するにはどうすればよいですか?

答え1

2.26より前のGNU libcバージョンとx86_64を含むいくつかのアーキテクチャでは、libcは渡された関数(パラメータとして値を返すため、任意の16を渡さない)から返され、最終的にclone()呼び出されます。これにより、すべてのスレッド(exit_group()プロセス全体)が終了します。

固定されています今回提出してください(望むより対応するエラーレポート)。

commit 3f823e87ccbf3723eb4eeb63b0619f1a0ceb174e
Author: Adhemerval Zanella <[email protected]>
Date:   Thu Jun 22 08:49:34 2017 -0300

   Call exit directly in clone (BZ #21512)

   On aarch64, alpha, arm, hppa, mips, nios2, powerpc, sh, sparc, tile,
   and x86_64 the clone syscall jumps to _exit after the child execution
   and the function ends the process execution by calling exit_group.
   This behavior have a small issue where threads created with
   CLONE_THREAD using clone syscall directly will eventually exit the
   whole group altogether instead of just the thread created.  Also,
   s390, microblaze, ia64, i386, and m68k differs by calling exit
   syscall directly.

   This patch changes all architectures to call the exit syscall
   directly, as for s390, microblaze, ia64, i386, and m68k.  This do not
   have change glibc internal behavior in any sort, since the only
   usage of clone implementation in posix_spawn calls _exit directly
   in the created child (fork uses a direct call to clone).

   Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
   powerpc-linux-gnu, powerpc64le-linux-gnu, sparc64-linux-gnu,
   and sparcv9-linux-gnu.

exit以前のバージョンでは、syscall(syscall(SYS_exit, 0))を直接呼び出すことでこの問題を解決できますreturn。または、関数を変更したくない場合は、次clone()のように定義されたラッパー関数を渡してください。

int wrapper(void *arg)
{
  syscall(SYS_exit, t2_thread(arg));
  return 0; /* never reached */
}

関連情報