スレッドを殺すためにどのように、楽で約束の実行を停止

Tinmarino:

私は上の実行中の約束に停止するのを待つ(例外を送信)を探していますSIGINT与えられた例のdocは、全体のプロセスだけでなく、1つのワーカーを終了します。

誰かのノウハウは、どのように「殺す」、「スケジュール取消し」、「停止」実行中のスレッドにしていますか?

これがためであるP6-jupyterカーネルの問題や、このREPLの問題

現在のソリューションは、REPLを再起動するが、ブロックされたスレッドを殺していません

await Promise.anyof(
  start {
      ENTER $running = True;
      LEAVE $running = False;
      CATCH {
          say $_;
          reset;
      }
      $output :=
        self.repl-eval($code,:outer_ctx($!save_ctx),|%adverbs);
  },
  $ctrl-c
);
ジョナサン・ワージントン:

ショートバージョン:、このために使用するプロセスをスレッドを使用しないでください。おそらく、実行中のプロセスを強制終了すると、一般的にこのような状況で達成することができる最善のことです。

長い答え:まず、それは問題で少し混乱を解消すると便利です。

まず第一に、「ランニングのようなものはありませんPromise」。Promise非同期操作の結果を伝達するためのデータ構造です。startブロックは、実際に3つのことをやっています:

  1. 作成Promise(それが評価されています)
  2. 実行するためにいくつかのコードのスケジュール
  3. 維持又は破断することによって、そのコードを実行の結果が反映されていることを配置します Promise

それは少しアカデミックに聞こえるかもしれませんが、本当に重要ことがあります。Promise最終的に維持するか、それを壊すことになります何の何の意識を持っていません。

第二に、startブロックではない-少なくとも、内蔵のスケジューラとは-スレッドに裏打ちされたのではなく、スレッドプールで実行されます。あなたがスレッドを「取る」への道を見つけ出すことができたとしても、スレッドプールスケジューラは、それが消えるの作業キューから食べることを期待していたスレッドの1つを有すると幸せになるだろうされていません。あなたは本当に新鮮なスレッドに戻って作業を行うたびに、独自のスケジューラを書き、まだ完全な解決策ではないことでした。どのようなコードの一部ならば、ユーザは、自身のスケジュール作業の実行を要求した、その後、awaitということです?そして、実際に停止する事をもたらすために殺すために誰のスレッドはありません。

レッツは、我々はこのすべてを解決するために管理しなかったこと、しかし、仮定、そして私たちは本当に(協同組合の状況はかなり簡単です彼らの協力なしに殺したいという私たちは自分自身の1つまたは複数のスレッドのリストを取得し、私たちが使用Promiseしていることをコードポーリングを持っていますしょっちゅう及びdieその解除があればPromise、これまで保たれている/壊れました)。

何にもブロックされたスレッドを停止できるようにしたいと考えて、そのようなメカニズムは、(単に計算するだけでなく、I / O、ロック、などではない)(例えばMoarVMなど)基本的なランタイムから深い統合と協力が必要になります。例えば、現在、(ほとんどの場合、全体としてVMをデッドロック)災害になりますガベージコレクションを実行しているスレッドをキャンセルしようとしています。殺されたスレッドがロックを保持、などされた場合、それは割り込みに安全ではありません操作して途中だった場合、他の不幸のキャンセル時間がメモリ破損につながる可能性があり、他の場所でデッドロック。したがって、一つは安全なポインティングメカニズムのいくつかの種類が必要になります。(我々はすでに、それはGCに安全なとき知ってMoarVMにおけるそれらのラインに沿って物事を持っている、しかし、キャンセルは異なる要求を意味します。これはおそらく、クロスカットVMのコードベースの多数の部品を。)

そして、それがすべてではありません:楽言語レベルで同じ状況が繰り返されすぎ。Lock::Async例えば、基本的なランタイムが認識していることをロックのようなものではありません。おそらくできる最善の一つはコールスタックを切断し、すべての実行しようとしているLEAVEフェイザーを。人々が使用している場合、いくつかの希望が(ありますそのように.protectする方法を、彼らは呼び出された場合lockと、unlock明示的に、我々は)のために行われています。しかし、我々は、リソースをリークしないように管理していても(すでに大が尋ねる)、我々はまだ知らない - 一般的に - 私たちは殺されたコードは、一貫性のある状態の任意の種類で世界を残している場合。REPLの文脈では、これは、同じグローバル状態にアクセスフォローアップの実行中に怪しげな成果につながる可能性があります。それはおそらく迷惑なんだが、何本当に私を怖がらせることは生産システムにおける、このようなキャンセルメカニズム使って人々である - 彼らは、我々はそれを実装するかどうか。

だから、効果的に、そのような機能を実装することは、ランタイムとRakudo自体に困難な作業にかなりの量をやってことになってしまう、その結果は巨大footgunだろう(私もちょうど最初に、間違って行くことができるすべてのものを列挙いませんでした)頭に来た数。これとは対照的に、プロセスを殺すことはそうないか一貫性の心配をありません、すべてのリソースをクリアし、プロセスは、独自のメモリ空間を持っています。

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=391787&siteId=1