Brokenプロセスはいつ解放されるのか?

数日前にacidについて書いたとき,「Brokenプロセスはいつまで残っているのだろうか?」という疑問が残った.そこで,Brokenプロセス周りについて調べてみた.

Brokenプロセスに関係しそうなコードを探していたら,port/proc.cに,次のようなコードが見つかった.addbrokenは引数で渡されたプロセスをbrokenという構造体に保持しているのだけど,保持するプロセス数はNBROKENでdefineされている4つだけなのだ.実際に前回使ったプログラムで確認してみたが,Brokenプロセスは4つより増えず,古いプロセスから解放されてしまうようだ.したがって,システムがBrokenプロセスだらけになることは避けられるが,なぜ4つになのか(十分?)はわからない...

  966: #define NBROKEN 4
  967: struct
  968: {
  969:         QLock;
  970:         int    n;
  971:         Proc   *p[NBROKEN];
  972: }broken;
  973: 
  974: void
  975: addbroken(Proc *p)
  976: {
  977:         qlock(&broken);
  978:         if(broken.n == NBROKEN) {
  979:                 ready(broken.p[0]);
  980:                 memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1));
  981:                 --broken.n;
  982:         }
  983:         broken.p[broken.n++] = p;
  984:         qunlock(&broken);
  985: 
  986:         edfstop(up);
  987:         p->state = Broken;
  988:         p->psstate = 0;
  989:         sched();
  990: }

BrokenプロセスがNBROKEN個以上になった場合,一番古いプロセスをレディキューにキューイングして,再度スケジューリングする.おや,Brokenプロセスを再度実行しては問題ではと思われるだろう.

それは,どうやってaddbrokenがどう呼ばれてきたかを見ればわかる.あるプロセスが異常終了する場合,フォールト処理の後,プロセスを終了するために,pexitを呼ぶ.この際,第二引数のfreememが0である必要がある.1127行目からaddbrokenが呼ばれ,プロセスがBroken状態になる.そして,BrokenプロセスがReady状態になってから,再度スケジューリングされた場合は,1127行目の後から処理が再開される.したがって,Moribund状態になり,schedinitでDead状態になる.非常にシンプルでわかりやすい.

 1025: void
 1026: pexit(char *exitstr, int freemem)
 1027: {

 1126:         if(!freemem)
 1127:                 addbroken(up);
 
 1163:         up->state = Moribund;
 1164:         sched();
 1165:         panic("pexit");
 1166: }

これからわかるようにUNIXではコアダンプはまさに検死だけど,Plan9のBrokenプロセスは,瀕死ではあるけど,まだ生きている.

Brokenプロセスをファイルにコアダンプする方法があるのかは,まだ追ってない.procdumpって関数があるけど,メッセージを表示するためのもので,コアを吐くものじゃないな.