yohhoyの日記

技術的メモをしていきたい日記

readdir/readdir_r関数のあれこれ

POSIX環境にて提供されるreaddir、readdir_r関数に関するメモ。

まとめ:

  • 事実上スレッドセーフが保証される readdir 関数を使うこと。将来のPOSIX規格でスレッドセーフ保証が追加予定。
  • readdir_r 関数を利用してはならない。POSIXからも廃止予定であり、GLIBC 2.24以降で非推奨となった。

POSIX

2016年9月現在、POSIX(POSIX.1-2008)ではreaddir関数のスレッドセーフ性は保障されない。POSIX規格(IEEE Std 1003.1-2013)より該当箇所を引用。

SYNOPSIS

#include <dirent.h>
struct dirent *readdir(DIR *dirp);
int readdir_r(DIR *restrict dirp, struct dirent *restrict entry,
       struct dirent **restrict result);

DESCRIPTION
The readdir() function need not be thread-safe.

readdir, readdir_r - read a directory

2.9.1 Thread-Safety
All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe.

  • (snip)
  • readdir()
  • (snip)
2. General Information, 2.9 Threads

readdir関数のスレッドセーフ版としてreaddir_r関数が存在するが、同関数が依存*1しているNAME_MAX定数定義の曖昧さからバッファオーバーフロー脆弱性につながるとの指摘がされている。この問題はAustin Group Issue 696で扱われており、2015年10月時点で「readdir_r関数は将来的に廃止」の方向で結論が出ている。

Linux/GLIBC

Linux/GLIBC実装では、readdir関数のスレッドセーフ性が保障*2されている。また、モダンな実装ではreaddir関数がスレッドセーフであることに言及し、POSIX規格側が更新されるべきとしている。

ATTRIBUTES
In the current POSIX.1 specification (POSIX.1-2008), readdir() is not required to be thread-safe. However, in modern implementations (including the glibc implementation), concurrent calls to readdir() that specify different directory streams are thread-safe. In cases where multiple threads must read from the same directory stream, using readdir() with external synchronization is still preferable to the use of the deprecated readdir_r(3) function. It is expected that a future version of POSIX.1 will require that readdir() be thread-safe when concurrently employed on different directory streams.

readdir(3) - Linux manual page

一方のreaddir_r関数は、2016/8/5リリースのGNU C Library 2.24で非推奨(deprecated)とされた*3

関連URL

*1:"The storage pointed to by entry shall be large enough for a dirent with an array of char d_name members containing at least {NAME_MAX}+1 elements."

*2:スレッドセーフが保障されるのは、異なるディレクトリ・ストリームに対して同時にreaddir関数を呼び出したときの安全性。同一ディレクトリ・ストリームに対する複数スレッドからの同時呼び出しは未定義動作を引き起こす。

*3:The GNU C Library version 2.24 is now available [LWN.net]