flockfile()是否安全?在Linux上已经被fclosed()编辑的FILE*?

Joh*_*hew 1 c linux thread-safety

这样的代码在linux上是安全的,在某种意义上1)它不会崩溃并且无法读取free()ed内存和2)freopen()ed文件与fclose()ed文件共享相同的lockcount?

线程1:

flockfile(file);
freopen("name", a", file);
funlockfile(file);
Run Code Online (Sandbox Code Playgroud)

线程2:

flockfile(file);
fputs("stuff", file);
funlockfile(file);
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 6

关闭时没有安全操作FILE*.来自fclose(3):

...对流的任何进一步访问(包括对fclose()的另一次调用)都会导致未定义的行为.

这是因为fclose(可能)释放文件指针指向的对象.

但是,当freopen锁被绑定到流而不是底层文件时,锁定流是完全安全的.事实上,根据flockfile(3):

stdio函数是线程安全的.

此外,freopenfreopen中也标记为"MT-safe" (3).因此,freopen必须在内部锁定1以避免关闭底层文件描述符,而另一个线程是,例如,freopen它.因此,从外部取出它必须是安全的(锁是可重复的).

最后,您实际上并不需要这些调用,flockfile因为所有文件操作都已经是线程安全的.


1我已经验证(通过阅读源代码)glibc和openbsd的libc(也用于android)在freopen调用时在内部锁定流.

glibc freopen代码打开:

FILE*
freopen (filename, mode, fp)
     const char* filename;
     const char* mode;
     FILE* fp;
{
  FILE *result;
  CHECK_FILE (fp, NULL);
  if (!(fp->_flags & _IO_IS_FILEBUF))
    return NULL;
  _IO_acquire_lock (fp); // <-- This a macro that calls the private equivalent of flockfile and does some gcc cleanup magic.
Run Code Online (Sandbox Code Playgroud)

并结束:

  _IO_release_lock (fp);
  return result;
}
Run Code Online (Sandbox Code Playgroud)