📌
[Bug #20586] 特定の条件下で Dir.glob の戻り値が意図しない結果になっているというバグ報告
[Bug #20586] Some filesystem calls in dir.c are missing error handling and can return incorrect results if interrupted
- 特定の条件下で
Dir.glob
の戻り値が意図しない結果になっているというバグ報告 - 具体的には
datadog
のプロファイラを有効にしているとおかしくなるらしい- 報告者は
datadog
の開発者でそういう問い合わせがあったらしい - https://github.com/DataDog/dd-trace-rb/issues/3450
- 報告者は
# プロファイラが無効なとき
irb(main):002:0> Dir.glob('/gcsfuse/t*')
=> ["/gcsfuse/test.html", "/gcsfuse/test.txt"]
# プロファイラが有効なとき
irb(main):002:0> Dir.glob('/gcsfuse/t*')
=> []
- 原因自体は
dir.c
のdir_each_entry
でエラーハンドリングがうまくできてないのが要因ぽいみたいですね?-
READDIR
は『ディレクトリストリームの末尾に達した場合』にNULL
を返すが、何らかの原因でエラーになった場合もNULL
を返す - 今回の datadog のケースでは後者の『エラーが発生している状態』になっているがそこがハンドリングされていないので空の配列を返しているぽい
-
static VALUE
dir_each_entry(VALUE dir, VALUE (*each)(VALUE, VALUE), VALUE arg, int children_only)
{
struct dir_data *dirp;
struct dirent *dp;
IF_NORMALIZE_UTF8PATH(int norm_p);
GetDIR(dir, dirp);
rewinddir(dirp->dir);
IF_NORMALIZE_UTF8PATH(norm_p = need_normalization(dirp->dir, RSTRING_PTR(dirp->path)));
// ここでエラーが発生したときに errorno をみてエラーハンドリングしてないのが原因ぽい
while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
// ... do things
}
return dir;
}
-
datadog
側の期待値としては『間違った値を返すのではなくて例外を発生してほしい』とのこと、それはそう
Discussion