2011-12-05 9 views
6

Java ProcessBuilderで奇妙な問題が発生しました。 Whateverのインスタンスのjava.io.IOException:error = 11

R --slave --args $1 $2 <whatever1.R >> r.log  

荷重を固定サイズ(35)のExecutorServiceに提出されている:コードは

public class Whatever implements Runnable 
{ 

public void run(){ 
     //someIdentifier is a randomly generated string 
     String in = someIdentifier + "input.txt"; 
     String out = someIdentifier + "output.txt"; 
     ProcessBuilder builder = new ProcessBuilder("./whateveer.sh", in, out); 
     try { 
      Process process = builder.start(); 
      process.waitFor(); 
     } catch (IOException e) { 
      log.error("Could not launch process. Command: " + builder.command(), e); 
     } catch (InterruptedException ex) { 
      log.error(ex); 
     } 
} 

} 

読み出しwhatever.sh(やや簡略化した形で)を以下に示します。残りのアプリケーションはすべてが完了するのを待ってCountdownLatchで実装されます。すべては、次の例外をスローする前に、数時間(科学のLinux 5.0、Javaのバージョン「1.6.0_24」)のために正常に動作:

java.io.IOException: Cannot run program "./whatever.sh": java.io.IOException: error=11, Resource temporarily unavailable 
    at java.lang.ProcessBuilder.start(Unknown Source) 
... rest of stack trace omitted... 

誰もこれが何を意味するのかのアイデアを持っていますか? java.io.IOException: error=11のgoogle/bing検索結果に基づいて、それは例外の最も一般的なものではなく、私は完全に困惑しています。

私は野生であり、教育を受けていないと思うので、同じファイルを同時に起動しようとするスレッドが多すぎます。しかし、問題を再現するには数時間のCPU時間がかかります。したがって、私は小さい数字で試していません。

ご意見をいただければ幸いです。

+0

Javaプロセスの開いているファイルを 'lsof'でチェックしましたか? – lidaobing

+1

errno 11または12か両方、あるいはその両方ですか? –

+0

エラー= 11のみ – mbatchkarov

答えて

6

error=11はほぼ確実EAGAINエラーコードです:

$ grep EAGAIN asm-generic/errno-base.h 
#define EAGAIN  11 /* Try again */ 

clone(2)システムコール文書EAGAINエラーリターン:

EAGAIN Too many processes are already running. 

fork(2)システムコール文書2 EAGAINエラーを返す:

EAGAIN fork() cannot allocate sufficient memory to copy the 
      parent's page tables and allocate a task structure for 
      the child. 

    EAGAIN It was not possible to create a new process because 
      the caller's RLIMIT_NPROC resource limit was 
      encountered. To exceed this limit, the process must 
      have either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE 
      capability. 

メモリが本当に低かった場合は、システムログにほとんど確実に表示されます。システムメモリが不足している可能性のあるメッセージについては、dmesg(1)出力または/var/log/syslogを確認してください。

プロセスごとのユーザー制限またはシステム全体の最大プロセス数のいずれかが実行されている可能性が非常に高いです。おそらくあなたのプロセスのうちの1つがゾンビを適切に取り戻していないでしょうか?これは、時間をかけてps(1)出力をチェックして見つけることは非常に簡単になります:

while true ; do ps auxw >> ~/processes ; sleep 10 ; done 

あなたが困っている前に、それは本当に時間がかかるなければ(たぶん、毎分または10分を確認してください。)

ゾンビを刈り取っていない場合は、ProcessBuilderに何をしなくても、waitpid(2)を使って死んだ子供たちを刈り取ってください。

あなたは合法的にあなたのrlimitsが許すよりも、より多くのプロセスを実行している場合、あなたはあなたのbash(1)スクリプト(rootとして実行されている場合)にulimitを使用するか、nprocプロパティの/etc/security/limits.confでより高い制限を設定する必要があります。

代わりにシステム全体のプロセス制限を実行している場合は、/proc/sys/kernel/pid_maxに大きな値を書き込む必要があります。いくつかの(短い)詳細については、proc(5)を参照してください。

+0

ありがとう、それは正しい方向に私を導く。コード内のバグにより、新しいスレッドが既存のスレッドを再利用するのではなく、ループ内に作成されて、最終的には説明された問題が発生していました。 – mbatchkarov

+0

それは 'builder.start()'コールではありませんでした_specifically_だが、問題を報告しているコードのほんの一部です。良いデバッグ。 :) – sarnold

+0

さて、本当に 'builder.start()'は失敗しましたが、アプリケーションの別の部分がすでに使用可能なリソースを使い果たしてしまったため失敗しました。あなたのポストで言及したように、プロセスをフォークするには一定のメモリが必要です。 – mbatchkarov

2

errno 11は、 "リソースは一時的に利用できません"という意味です。これは通常、メモリの問題であり、スレッドまたはソケットが作成されないようにすることができます。

errno 12は「メモリを割り当てることができません」を意味します。これはメモリを獲得することの失敗です。メモリの直接呼び出しです(メモリが必要なリソースではなく)。

この問題を回避する必要があるシステムのスワップ領域を増やしてみます。