Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12626] ファイルの概要

本コミットは、Go言語のruntime/cgoパッケージにおけるLinux環境でのシグナルマスキングに関する修正です。具体的には、pthread_create呼び出し時に発生しうるシグナル関連の問題を解決し、スレッド作成の堅牢性を向上させることを目的としています。この修正は、GoプログラムがCgoを介してCライブラリと連携する際に、予期せぬシグナルによってスレッドの初期化が妨げられる可能性に対処しています。

コミット

  • コミットハッシュ: 9eeb90945eb56edc9095c662741b89170e522419
  • Author: Mikio Hara mikioh.mikioh@gmail.com
  • Date: Wed Mar 14 13:07:25 2012 +0900

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/9eeb90945eb56edc9095c662741b89170e522419

元コミット内容

runtime/cgo: linux signal masking

Fixes #3314.
Fixes #3101 (again).

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5820047

変更の背景

このコミットは、Go言語のruntime/cgoがLinux上で新しいスレッドを作成する際に発生していた、シグナル関連のバグを修正するために導入されました。具体的には、以下の2つの問題(Go issue)を解決することを目的としています。

  • Issue #3314: "runtime/cgo: pthread_create fails if a signal is pending" (保留中のシグナルがあるとpthread_createが失敗する)
  • Issue #3101: "runtime/cgo: pthread_create fails if a signal is pending" (再度、保留中のシグナルがあるとpthread_createが失敗する)

これらの問題は、pthread_createが新しいスレッドを作成する際に、親スレッドに保留されているシグナルが子スレッドに継承され、そのシグナルがスレッドの初期化プロセスに干渉することで発生していました。特に、pthread_createが内部的に使用するシステムコールが、シグナルによって中断される可能性がありました。これにより、スレッドの作成が失敗したり、予期せぬ動作を引き起こしたりする可能性がありました。

この修正は、以前にも同様の問題(Issue #3101)に対する試みがあったものの、完全に解決されていなかったため、「(again)」と付記されています。これは、シグナル処理の複雑さと、異なるLinuxカーネルバージョンや環境での挙動の違いが原因である可能性があります。

前提知識の解説

Cgo (Go言語とC言語の相互運用)

Cgoは、GoプログラムがC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。Goはシステムプログラミング言語ですが、既存のCライブラリやOSのAPIを直接利用する必要がある場合にCgoが用いられます。Cgoを使用すると、GoのランタイムとCのランタイムが共存することになり、特にスレッド管理やシグナル処理において、両者の挙動の整合性を保つことが重要になります。

pthread_create

pthread_createは、POSIXスレッド(pthreads)ライブラリで提供される関数で、新しいスレッドを作成するために使用されます。この関数は、新しいスレッドの属性(スタックサイズなど)を指定するpthread_attr_t構造体と、新しいスレッドが実行を開始する関数へのポインタ、およびその関数に渡す引数を取ります。pthread_createは、GoのランタイムがCgoを介してCのコードから新しいOSスレッドを起動する際に内部的に使用されることがあります。

Linuxシグナル処理

Linux(およびPOSIXシステム)におけるシグナルは、プロセスやスレッドに対して非同期的に通知されるイベントです。シグナルは、ハードウェア例外(例: ゼロ除算、不正なメモリアクセス)やソフトウェアイベント(例: ユーザーからのCtrl+C、タイマー満了、子プロセスの終了)によって生成されます。

  • シグナルマスク: 各スレッドは、ブロックするシグナルのセット(シグナルマスク)を持っています。シグナルがブロックされている場合、そのシグナルはスレッドに配信されず、保留状態になります。シグナルがブロック解除されると、保留されていたシグナルが配信されます。
  • sigset_t: シグナルのセットを表すデータ型です。
  • sigfillset(sigset_t *set): setが指すシグナルセットを、すべての標準シグナルを含むように初期化します。つまり、すべてのシグナルをブロック対象として設定します。
  • sigprocmask(int how, const sigset_t *set, sigset_t *oldset): 呼び出し元のスレッドのシグナルマスクを変更するために使用されます。
    • how: シグナルマスクの変更方法を指定します。
      • SIG_SETMASK: setで指定されたシグナルセットを新しいシグナルマスクとして設定します。
      • SIG_BLOCK: setで指定されたシグナルを現在のシグナルマスクに追加します。
      • SIG_UNBLOCK: setで指定されたシグナルを現在のシグナルマスクから削除します。
    • set: howで指定された操作に使用されるシグナルセットへのポインタです。
    • oldset: 変更前のシグナルマスクを保存するためのポインタです。NULLの場合、古いマスクは保存されません。

シグナルとスレッド作成の相互作用

pthread_createのようなシステムコールは、シグナルによって中断される可能性があります。親スレッドに保留されているシグナルがある場合、新しい子スレッドは親スレッドのシグナルマスクを継承します。しかし、シグナルがpthread_createの実行中に配信されると、そのシステムコールが中断され、スレッドの作成が失敗する可能性があります。これは、特にGoのランタイムがCgoを介して外部のCライブラリと連携し、そのCライブラリが新しいスレッドを生成するようなシナリオで問題となります。

技術的詳細

このコミットの技術的な核心は、pthread_createを呼び出す直前にすべてのシグナルを一時的にブロックし、pthread_createが完了した後に元のシグナルマスクを復元するというアプローチです。これにより、pthread_createの実行中に予期せぬシグナルが配信され、スレッド作成プロセスが中断されることを防ぎます。

具体的な手順は以下の通りです。

  1. シグナルセットの準備: sigset_t ignsigset_t osetという2つのシグナルセット変数を宣言します。ignはすべてのシグナルをブロックするために使用され、osetpthread_create呼び出し前の元のシグナルマスクを保存するために使用されます。
  2. すべてのシグナルのブロック: sigfillset(&ign)を呼び出してignにすべてのシグナルを含め、sigprocmask(SIG_SETMASK, &ign, &oset)を呼び出して現在のスレッドのシグナルマスクをignに設定します。これにより、pthread_createが実行されている間、すべてのシグナルがブロックされ、保留状態になります。同時に、元のシグナルマスクがosetに保存されます。
  3. スレッドの作成: pthread_createを呼び出して新しいスレッドを作成します。この間、シグナルはブロックされているため、pthread_createはシグナルによる中断なしに安全に実行できます。
  4. 元のシグナルマスクの復元: pthread_createが成功したかどうかにかかわらず、sigprocmask(SIG_SETMASK, &oset, nil)を呼び出して、スレッド作成前の元のシグナルマスクを復元します。これにより、シグナル処理の挙動がpthread_create呼び出し前と同じ状態に戻ります。

このアプローチは、クリティカルセクション(ここではpthread_createの呼び出し)をシグナルから保護するための標準的な手法です。これにより、GoのCgoランタイムがLinux上でより堅牢にスレッドを作成できるようになります。

コアとなるコードの変更箇所

変更はsrc/pkg/runtime/cgo/gcc_linux_386.csrc/pkg/runtime/cgo/gcc_linux_amd64.cの2つのファイルに適用されています。これらはそれぞれ32ビット(i386)と64ビット(amd64)のLinuxアーキテクチャ向けのCgoランタイムコードです。変更内容は両ファイルでほぼ同じです。

diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c
index 8401a75caa..7d84acc11e 100644
--- a/src/pkg/runtime/cgo/gcc_linux_386.c
+++ b/src/pkg/runtime/cgo/gcc_linux_386.c
@@ -4,6 +4,7 @@
 
 #include <pthread.h>
 #include <string.h>
+#include <signal.h>
 #include "libcgo.h"
 
 static void *threadentry(void*);
@@ -26,10 +27,14 @@ void
 libcgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
+\tsigset_t ign, oset;\n \tpthread_t p;\n \tsize_t size;\n \tint err;\n \n+\tsigfillset(&ign);\n+\tsigprocmask(SIG_SETMASK, &ign, &oset);\n+\n 	// Not sure why the memset is necessary here,
 	// but without it, we get a bogus stack size
 	// out of pthread_attr_getstacksize.  C'est la Linux.
@@ -39,6 +44,9 @@ libcgo_sys_thread_start(ThreadStart *ts)
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
+\n+\tsigprocmask(SIG_SETMASK, &oset, nil);\n+\n 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
 		abort();
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c
index 6ce3333a85..28cbf78c52 100644
--- a/src/pkg/runtime/cgo/gcc_linux_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c
@@ -4,6 +4,7 @@
 
 #include <pthread.h>
 #include <string.h> // strerror
+#include <signal.h>
 #include "libcgo.h"
 
 static void* threadentry(void*);
@@ -26,14 +27,21 @@ void
 libcgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
+\tsigset_t ign, oset;\n \tpthread_t p;\n \tsize_t size;\n \tint err;\n \n+\tsigfillset(&ign);\n+\tsigprocmask(SIG_SETMASK, &ign, &oset);\n+\n 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
+\n+\tsigprocmask(SIG_SETMASK, &oset, nil);\n+\n 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
 		abort();

コアとなるコードの解説

変更されたコードは、libcgo_sys_thread_start関数内にあります。この関数は、GoランタイムがCgoを介して新しいOSスレッドを起動する際に呼び出されます。

  1. #include <signal.h>:

    • シグナル処理に関連する関数(sigset_t, sigfillset, sigprocmaskなど)を使用するために、signal.hヘッダーファイルがインクルードされています。
  2. sigset_t ign, oset;:

    • ign: すべてのシグナルをブロックするためのシグナルセットです。
    • oset: sigprocmask呼び出し前の元のシグナルマスクを保存するためのシグナルセットです。
  3. sigfillset(&ign);:

    • ignシグナルセットを、すべての標準シグナルを含むように初期化します。これにより、ignはすべてのシグナルをブロックするマスクとして機能するようになります。
  4. sigprocmask(SIG_SETMASK, &ign, &oset);:

    • この行が変更の核心です。
    • SIG_SETMASKは、現在のスレッドのシグナルマスクをignで指定されたセットに完全に置き換えることを意味します。
    • これにより、pthread_createが呼び出される直前に、すべてのシグナルが一時的にブロックされます。
    • 同時に、変更前の元のシグナルマスクがosetに保存されます。これは、pthread_createの呼び出し後に元の状態に戻すために必要です。
  5. err = pthread_create(&p, &attr, threadentry, ts);:

    • 新しいスレッドを作成する実際の呼び出しです。この呼び出しは、シグナルがブロックされている「安全な」期間中に実行されます。
  6. sigprocmask(SIG_SETMASK, &oset, nil);:

    • pthread_createの呼び出し後、元のシグナルマスクを復元します。
    • osetに保存されていたシグナルマスクが現在のスレッドのマスクとして設定されます。
    • nilは、この呼び出しで古いシグナルマスクを保存する必要がないことを示します。

この一連の操作により、pthread_createの実行中にシグナルが配信されて処理を中断する可能性が排除され、スレッド作成の信頼性が向上します。

関連リンク

参考にした情報源リンク

[インデックス 12626] ファイルの概要

本コミットは、Go言語のruntime/cgoパッケージにおけるLinux環境でのシグナルマスキングに関する修正です。具体的には、pthread_create呼び出し時に発生しうるシグナル関連の問題を解決し、スレッド作成の堅牢性を向上させることを目的としています。この修正は、GoプログラムがCgoを介してCライブラリと連携する際に、予期せぬシグナルによってスレッドの初期化が妨げられる可能性に対処しています。

コミット

  • コミットハッシュ: 9eeb90945eb56edc9095c662741b89170e522419
  • Author: Mikio Hara mikioh.mikioh@gmail.com
  • Date: Wed Mar 14 13:07:25 2012 +0900

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/9eeb90945eb56edc9095c662741b89170e522419

元コミット内容

runtime/cgo: linux signal masking

Fixes #3314.
Fixes #3101 (again).

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5820047

変更の背景

このコミットは、Go言語のruntime/cgoがLinux上で新しいスレッドを作成する際に発生していた、シグナル関連のバグを修正するために導入されました。具体的には、以下の2つの問題(Go issue)を解決することを目的としています。

  • Issue #3314: "runtime/cgo: pthread_create fails if a signal is pending" (保留中のシグナルがあるとpthread_createが失敗する)
  • Issue #3101: "runtime/cgo: pthread_create fails if a signal is pending" (再度、保留中のシグナルがあるとpthread_createが失敗する)

これらの問題は、pthread_createが新しいスレッドを作成する際に、親スレッドに保留されているシグナルが子スレッドに継承され、そのシグナルがスレッドの初期化プロセスに干渉することで発生していました。特に、pthread_createが内部的に使用するシステムコールが、シグナルによって中断される可能性がありました。これにより、スレッドの作成が失敗したり、予期せぬ動作を引き起こしたりする可能性がありました。

この修正は、以前にも同様の問題(Issue #3101)に対する試みがあったものの、完全に解決されていなかったため、「(again)」と付記されています。これは、シグナル処理の複雑さと、異なるLinuxカーネルバージョンや環境での挙動の違いが原因である可能性があります。Goランタイムはプログラム起動時にシグナルハンドリングを制御し、独自のシグナルハンドラをインストールしますが、Cgoを介して非Goコードがpthread_createのような関数で新しいスレッドを作成する場合、Goランタイムが管理するスレッドのシグナルマスクを変更すべきではありません。しかし、非Goコードが独自に作成したスレッドは、自由にシグナルマスクを設定できます。このコミットは、pthread_create呼び出し時のシグナルマスクの挙動を適切に管理することで、この問題を解決しようとしています。

前提知識の解説

Cgo (Go言語とC言語の相互運用)

Cgoは、GoプログラムがC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。Goはシステムプログラミング言語ですが、既存のCライブラリやOSのAPIを直接利用する必要がある場合にCgoが用いられます。Cgoを使用すると、GoのランタイムとCのランタイムが共存することになり、特にスレッド管理やシグナル処理において、両者の挙動の整合性を保つことが重要になります。Goの起動コードは、非Goコードの起動コードよりも先に実行され、シグナルハンドラを設定します。非Goコードが独自のシグナルハンドラをインストールしようとする場合、Goランタイムのハンドラと干渉しないように注意深く行う必要があります。

pthread_create

pthread_createは、POSIXスレッド(pthreads)ライブラリで提供される関数で、新しいスレッドを作成するために使用されます。この関数は、新しいスレッドの属性(スタックサイズなど)を指定するpthread_attr_t構造体と、新しいスレッドが実行を開始する関数へのポインタ、およびその関数に渡す引数を取ります。pthread_createは、GoのランタイムがCgoを介してCのコードから新しいOSスレッドを起動する際に内部的に使用されることがあります。Linuxでは、pthread_createで作成された新しいスレッドは、作成元のスレッドのシグナルマスクのコピーを継承します。ただし、保留中のシグナルセットは空です。

Linuxシグナル処理

Linux(およびPOSIXシステム)におけるシグナルは、プロセスやスレッドに対して非同期的に通知されるイベントです。シグナルは、ハードウェア例外(例: ゼロ除算、不正なメモリアクセス)やソフトウェアイベント(例: ユーザーからのCtrl+C、タイマー満了、子プロセスの終了)によって生成されます。

  • シグナルマスク: 各スレッドは、ブロックするシグナルのセット(シグナルマスク)を持っています。シグナルがブロックされている場合、そのシグナルはスレッドに配信されず、保留状態になります。シグナルがブロック解除されると、保留されていたシグナルが配信されます。シグナルハンドラはプロセス内のすべてのスレッドで共有されますが、シグナルマスクはスレッドごとに独立しています。
  • sigset_t: シグナルのセットを表すデータ型です。
  • sigfillset(sigset_t *set): setが指すシグナルセットを、すべての標準シグナルを含むように初期化します。つまり、すべてのシグナルをブロック対象として設定します。
  • sigprocmask(int how, const sigset_t *set, sigset_t *oldset): 呼び出し元のスレッドのシグナルマスクを変更するために使用されます。
    • how: シグナルマスクの変更方法を指定します。
      • SIG_SETMASK: setで指定されたシグナルセットを新しいシグナルマスクとして設定します。
      • SIG_BLOCK: setで指定されたシグナルを現在のシグナルマスクに追加します。
      • SIG_UNBLOCK: setで指定されたシグナルを現在のシグナルマスクから削除します。
    • set: howで指定された操作に使用されるシグナルセットへのポインタです。
    • oldset: 変更前のシグナルマスクを保存するためのポインタです。NULLの場合、古いマスクは保存されません。

シグナルとスレッド作成の相互作用

pthread_createのようなシステムコールは、シグナルによって中断される可能性があります。親スレッドに保留されているシグナルがある場合、新しい子スレッドは親スレッドのシグナルマスクを継承します。しかし、シグナルがpthread_createの実行中に配信されると、そのシステムコールが中断され、スレッドの作成が失敗する可能性があります。これは、特にGoのランタイムがCgoを介して外部のCライブラリと連携し、そのCライブラリが新しいスレッドを生成するようなシナリオで問題となります。

技術的詳細

このコミットの技術的な核心は、pthread_createを呼び出す直前にすべてのシグナルを一時的にブロックし、pthread_createが完了した後に元のシグナルマスクを復元するというアプローチです。これにより、pthread_createの実行中に予期せぬシグナルが配信され、スレッド作成プロセスが中断されることを防ぎます。

具体的な手順は以下の通りです。

  1. シグナルセットの準備: sigset_t ignsigset_t osetという2つのシグナルセット変数を宣言します。ignはすべてのシグナルをブロックするために使用され、osetpthread_create呼び出し前の元のシグナルマスクを保存するために使用されます。
  2. すべてのシグナルのブロック: sigfillset(&ign)を呼び出してignにすべてのシグナルを含め、sigprocmask(SIG_SETMASK, &ign, &oset)を呼び出して現在のスレッドのシグナルマスクをignに設定します。これにより、pthread_createが実行されている間、すべてのシグナルがブロックされ、保留状態になります。同時に、元のシグナルマスクがosetに保存されます。
  3. スレッドの作成: pthread_createを呼び出して新しいスレッドを作成します。この間、シグナルはブロックされているため、pthread_createはシグナルによる中断なしに安全に実行できます。
  4. 元のシグナルマスクの復元: pthread_createが成功したかどうかにかかわらず、sigprocmask(SIG_SETMASK, &oset, nil)を呼び出して、スレッド作成前の元のシグナルマスクを復元します。これにより、シグナル処理の挙動がpthread_create呼び出し前と同じ状態に戻ります。

このアプローチは、クリティカルセクション(ここではpthread_createの呼び出し)をシグナルから保護するための標準的な手法です。これにより、GoのCgoランタイムがLinux上でより堅牢にスレッドを作成できるようになります。

コアとなるコードの変更箇所

変更はsrc/pkg/runtime/cgo/gcc_linux_386.csrc/pkg/runtime/cgo/gcc_linux_amd64.cの2つのファイルに適用されています。これらはそれぞれ32ビット(i386)と64ビット(amd64)のLinuxアーキテクチャ向けのCgoランタイムコードです。変更内容は両ファイルでほぼ同じです。

diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c
index 8401a75caa..7d84acc11e 100644
--- a/src/pkg/runtime/cgo/gcc_linux_386.c
+++ b/src/pkg/runtime/cgo/gcc_linux_386.c
@@ -4,6 +4,7 @@
 
 #include <pthread.h>
 #include <string.h>
+#include <signal.h>
 #include "libcgo.h"
 
 static void *threadentry(void*);
@@ -26,10 +27,14 @@ void
 libcgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
+\tsigset_t ign, oset;\n \tpthread_t p;\n \tsize_t size;\n \tint err;\n \n+\tsigfillset(&ign);\n+\tsigprocmask(SIG_SETMASK, &ign, &oset);\n+\n 	// Not sure why the memset is necessary here,
 	// but without it, we get a bogus stack size
 	// out of pthread_attr_getstacksize.  C'est la Linux.
@@ -39,6 +44,9 @@ libcgo_sys_thread_start(ThreadStart *ts)
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
+\n+\tsigprocmask(SIG_SETMASK, &oset, nil);\n+\n 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
 		abort();
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c
index 6ce3333a85..28cbf78c52 100644
--- a/src/pkg/runtime/cgo/gcc_linux_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c
@@ -4,6 +4,7 @@
 
 #include <pthread.h>
 #include <string.h> // strerror
+#include <signal.h>
 #include "libcgo.h"
 
 static void* threadentry(void*);
@@ -26,14 +27,21 @@ void
 libcgo_sys_thread_start(ThreadStart *ts)
 {
 	pthread_attr_t attr;
+\tsigset_t ign, oset;\n \tpthread_t p;\n \tsize_t size;\n \tint err;\n \n+\tsigfillset(&ign);\n+\tsigprocmask(SIG_SETMASK, &ign, &oset);\n+\n 	pthread_attr_init(&attr);
 	pthread_attr_getstacksize(&attr, &size);
 	ts->g->stackguard = size;
 	err = pthread_create(&p, &attr, threadentry, ts);
+\n+\tsigprocmask(SIG_SETMASK, &oset, nil);\n+\n 	if (err != 0) {
 		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\\n", strerror(err));
 		abort();

コアとなるコードの解説

変更されたコードは、libcgo_sys_thread_start関数内にあります。この関数は、GoランタイムがCgoを介して新しいOSスレッドを起動する際に呼び出されます。

  1. #include <signal.h>:

    • シグナル処理に関連する関数(sigset_t, sigfillset, sigprocmaskなど)を使用するために、signal.hヘッダーファイルがインクルードされています。
  2. sigset_t ign, oset;:

    • ign: すべてのシグナルをブロックするためのシグナルセットです。
    • oset: sigprocmask呼び出し前の元のシグナルマスクを保存するためのシグナルセットです。
  3. sigfillset(&ign);:

    • ignシグナルセットを、すべての標準シグナルを含むように初期化します。これにより、ignはすべてのシグナルをブロックするマスクとして機能するようになります。
  4. sigprocmask(SIG_SETMASK, &ign, &oset);:

    • この行が変更の核心です。
    • SIG_SETMASKは、現在のスレッドのシグナルマスクをignで指定されたセットに完全に置き換えることを意味します。
    • これにより、pthread_createが呼び出される直前に、すべてのシグナルが一時的にブロックされます。
    • 同時に、変更前の元のシグナルマスクがosetに保存されます。これは、pthread_createの呼び出し後に元の状態に戻すために必要です。
  5. err = pthread_create(&p, &attr, threadentry, ts);:

    • 新しいスレッドを作成する実際の呼び出しです。この呼び出しは、シグナルがブロックされている「安全な」期間中に実行されます。
  6. sigprocmask(SIG_SETMASK, &oset, nil);:

    • pthread_createの呼び出し後、元のシグナルマスクを復元します。
    • osetに保存されていたシグナルマスクが現在のスレッドのマスクとして設定されます。
    • nilは、この呼び出しで古いシグナルマスクを保存する必要がないことを示します。

この一連の操作により、pthread_createの実行中にシグナルが配信されて処理を中断する可能性が排除され、スレッド作成の信頼性が向上します。

関連リンク

参考にした情報源リンク