質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3029閲覧

C++20 Linux-GCC pthread-で他のスレッドを一時停止&再開させる

bjnes

総合スコア113

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/08/31 04:48

前提・実現したいこと

マルチスレッドで親スレッドや他スレッドからSuspend、Resume相当の操作を行いたい。
(他スレッドからの任意のSuspend、Resumeは本質的に危険だからやめたほうがいいという議論は、行わない方向でお願いします。)
なるべく、ThredFunc()内に自身がSuspend、Resumeするかどうか判断するコードは書きたくないです。

該当のソースコード

C++

1#include <iostream> 2#include <thread> 3#include <chrono> 4 5//OnとOffを5回1秒周期で出力します。 6void ThreadFunc(char ThreadName) 7{ 8 int i = 0; 9 while (i < 5) 10 { 11 //コンソール出力はMutexが取れているものとする(取れてませんが) 12 std::cout << ThreadName << " run::On" << i << std::endl; 13 std::this_thread::sleep_for(std::chrono::seconds(1)); 14 std::cout << ThreadName << " run::Off" << i << std::endl; 15 std::this_thread::sleep_for(std::chrono::seconds(1)); 16 i++; 17 } 18}; 19 20int main(int, char **) 21{ 22 auto th1 = std::thread(ThreadFunc, 'A'); //途中で止めたいスレッド 23 auto th2 = std::thread(ThreadFunc, 'B'); //最後まで走るスレッド 24 25 std::this_thread::sleep_for(std::chrono::seconds(2)); 26 //th1.suspend(); //この操作がしたい SUPECIAL::Suspend(th1);でも可。 27 th2.join(); 28 //th1.resume(); //この操作がしたい SUPECIAL::Resume(th1);でも可。 29 30 th1.join(); 31} 32

期待する出力メッセージ

以下のようなメッセージがでることを期待します。

A run::On0 B run::On0 B run::Off0 A run::Off0 A run::On1 B run::On1 A run::Off1 B run::Off1     B run::On2    #ここでth1.susupend() B run::Off2 B run::On3 B run::Off3 B run::On4 B run::Off4 A run::On2 A run::Off2 A run::On3 A run::Off3 A run::On4 A run::Off4

###考えていること
止めれるのであれば止めれたら嬉しいが、最低でも、子スレッドの関数コール時に__cyg_profile_func_enter()で止めれるようにしたい。
ながーくなりそうなので、面倒だなぁと感じますが、現在模索中です。

補足情報

gcc -v
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/lto-wrapper
ターゲット: x86_64-pc-linux-gnu
configure 設定: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --with-isl --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-install-libiberty --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-libunwind-exceptions --disable-werror gdc_include_dir=/usr/include/dlang/gdc
スレッドモデル: posix
Supported LTO compression algorithms: zlib zstd
gcc バージョン 10.2.0 (GCC)

uname -a
Linux @@@@ 5.8.5-arch1-1 #1 SMP PREEMPT Thu, 27 Aug 2020 18:53:02 +0000 x86_64 GNU/Linux

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

C++20標準ライブラリ、およびLinux環境のPThreadsライブラリでは 「他スレッドのサスペンド処理」 を提供しません。

Linuxカーネルでは LinuxThreads ではなく NPTL(Native POSIX Thread Library) が利用されますが、旧 LinuxThreads Frequently Asked Questions のPOSIXへの言及についてはNPTL現在も同じです。

E.4: How can I suspend and resume a thread from another thread? Solaris has the thr_suspend() and thr_resume() functions to do that; why don't you?

The POSIX standard provides no mechanism by which a thread A can suspend the execution of another thread B, without cooperation from B. The only way to implement a suspend/restart mechanism is to have B check periodically some global variable for a suspend request and then suspend itself on a condition variable, which another thread can signal later to restart B.

Notice that thr_suspend() is inherently dangerous and prone to race conditions. For one thing, there is no control on where the target thread stops: it can very well be stopped in the middle of a critical section, while holding mutexes. Also, there is no guarantee on when the target thread will actually stop. For these reasons, you'd be much better off using mutexes and conditions instead. The only situations that really require the ability to suspend a thread are debuggers and some kind of garbage collectors.

If you really must suspend a thread in LinuxThreads, you can send it a SIGSTOP signal with pthread_kill. Send SIGCONT for restarting it. Beware, this is specific to LinuxThreads and entirely non-portable. Indeed, a truly conforming POSIX threads implementation will stop all threads when one thread receives the SIGSTOP signal! One day, LinuxThreads will implement that behavior, and the non-portable hack with SIGSTOP won't work anymore.


(他スレッドからの任意のSuspend、Resumeは本質的に危険だからやめたほうがいいという議論は、行わない方向でお願いします。)

ご自身で言及されている通り、他スレッドのサスペンドは大変危険な処理です。自己責任で前掲FAQにあるSIGSTOP/SIGCONTシグナルを試してみてください。 NPTLではSIGSTOPはおそらく期待通りに機能しません

参考までに、StackOverflowのこの回答がやりたいことに最も近いかもしれません。いずれにせよ、Linuxシグナルとマルチスレッド実装に対する正確な理解が必要となります。

前掲FAQにもあるように、Solarisではスレッドサスペンド/レジュームAPIを提供しています。同スレッドをエミュレーションする Solaris-compatible Thread Library が存在しますのでどうしてもという場合は参考になるかもしれません。(ちらっと覗いた雰囲気では、サスペンドされる側にも相当な仕掛けを用意していましたが)

投稿2020/08/31 13:17

編集2020/08/31 14:17
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bjnes

2020/09/15 05:59

関数呼び出し時にサスベンドにするようなものを作っていますが、少し時間がかかりそうなので、 これをベストアンサーにさせていただきます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問