【问题标题】:Is it safe to flockfile() a FILE* that has been fclosed()ed on linux?在 linux 上 fclose() 的flockfile() 文件* 是否安全?
【发布时间】:2015-10-16 03:51:31
【问题描述】:

这样的代码在 linux 上是否安全,因为 1) 它不会崩溃并且无法读取 free()ed 内存,以及 2) freopen()ed 文件与 fclose()ed 文件共享相同的锁定计数?

线程 1:

flockfile(file);
freopen("name", a", file);
funlockfile(file);

线程2:

flockfile(file);
fputs("stuff", file);
funlockfile(file);

【问题讨论】:

  • 我无法给出答案,但我会在遇到的任何代码审查中质疑它。如果它是安全的,我希望在那里发表评论,将我引导到说它是安全的来源。
  • @John3136 还是谢谢
  • 为什么还需要 fclose 调用呢?

标签: c linux thread-safety


【解决方案1】:

已关闭的FILE* 上没有安全操作。来自fclose(3)

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

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

但是,在freopening 时锁定流是完全安全的,因为锁与流相关联,而不是底层文件。其实根据flockfile(3)

stdio 函数是线程安全的。

此外,freopenfreopen(3) 中也被标记为“MT 安全”。因此,freopen 必须在内部获取锁1 以避免在另一个线程(例如,freopening)时关闭底层文件描述符。所以,外带一定是安全的(锁是可重入的)。

最后,您实际上并不需要那些对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.

并以:

结束
  _IO_release_lock (fp);
  return result;
}

【讨论】:

  • 谢谢。我更新了这个问题,通过删除 fclose() 并留下 freopen() 来澄清它。你怎么看这个案子。
  • 谢谢。你有什么可以参考的东西来支持这个安全吗?
  • @JohnCashew,不幸的是,我找不到任何文件明确说明在持有锁的同时调用freopen 是安全的,但不可能以任何其他方式安全地实现freopen
猜你喜欢
  • 2020-06-13
  • 1970-01-01
  • 2020-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2013-03-26
相关资源
最近更新 更多