2009年1月25日日曜日

Mac OSとlinuxの EOF エラーハンドルの違い.

lessのように追記されるファイルから次々に読み込む場合,一度EOFが帰ってきたものに対してスリープして,再度読み込みを行ったりする.が,このときの挙動がlinuxとMac OSで違っていてはまった.
  while (1) {
    char * p = fgets(buf, 1000, fp);
    if (p == NULL) {
      sleep(1);
    } else {
      printf("%s\n", p);
    }
  }
このずさんなコードはlinuxやSolarisだとちゃんと動いて,ファイルに追記されると追従することができるのだが,Mac OSでは動かない.ファイルに追記しても,ずっとfgetsがNULLを返す.

ストリームの中にはすでにEOFに当ったという情報が保持されているのだけど,これを明示的にクリアしてやらないと,いけない,ということのようだ.もっとお行儀のいいコードはこんな感じ.そもそもNULLで返ってきたときに,EOFなのかエラーなのかをferrorでちゃんと見てやって,EOFのときだけ,clearerr()でクリアしてやる.こうするとMac OS でもちゃんと動く.

  while (true) {
    char * p = fgets(buf, 1000, fp);
    if (p == NULL) {
      if (ferror(fp)){
        printf("error, abort\n");
        break;
      }
      clearerr(fp);
      sleep(1);
    } else {
      printf("%s\n", p);
    }
  }
この違いは,きっとSys V系(Linux, Solaris)とBSD系(Mac OS X)に由来する違いなんだろうなあ...

0 件のコメント: