closures文件描述符的危险

在堆栈溢出问题中检查一个程序是否存在于bash脚本中 , 接受的答案指出closuresstderr是危险的:

(次要方面:有些人会build议2>& – 是相同的2> / dev / null但是更短 – 这是不正确的。2>& – closuresFD 2,当程序尝试写入stderr ,这与成功写入并丢弃输出(和危险的!)非常不同

  • 除了写作计划中的错误,还有什么其他危险的事情发生?
  • 可以使用2>& – 潜在地破坏写程序(即停止执行,不允许清理)?

是的,它会以令人兴奋和有趣的方式打破东西。

问题在于类Unix系统通常按顺序分配文件描述符。 当一个程序想要一个新的文件描述符时(即它们调用open()socket()和其他分配fd的函数),内核将find编号最小的“空闲”描述符。

想象一下,如果你愿意的话,你已经closures了fd 2(stderr)。 这个过程中的某些东西需要一个文件描述符(下一个打开的文件)。 内核去寻找一个免费的fd,看到fd 2没有被使用,并把它返回给程序。

现在,想象一下程序中的其他东西是想写给stderr的。 它盲目写入fd 2,因为stderr住在哪里。 除了现在没有。 如果幸运的话 ,fd 2只能以只读的方式打开,写入出错。 每个人都认为写入stderr将会一直成功,所以这会很有趣。 至less有可能的是,fd是读写(六个fopen (2)模式中的五个是写使能的 – r+aa+ww+ )以及应该去的消息stderr刚刚结束了飞溅whoknowswhere

更令人兴奋的是,*文件描述符在fork()上被inheritance。 这意味着每个孩子的过程也将有能力在任何意想不到的地方涂写。 更糟糕的是,甚至是“安全”的分叉策略,例如在exec之前所有的fds都被closures的情况下,通常不会碰到fds 0,1或2.所以你的小碎片几乎可以肯定存在于防止跨越过程边界的灾难的普通策略中。

你可能会说,“好吧,我永远不会使用写给stderr的图书馆,我会小心的不要写信给自己”。 对此,我只有两件事要说:

  1. 未来 – 你不会那么小心。 你会忘记你closures了stderr。
  2. 其他所有可能有不幸处理你的疯狂代码的人也不会那么小心。

朋友不要让朋友closuresstderr。 Womble出来。 滴麦克风

这可能会非常糟糕,导致未定义的行为。 检查我的旧问题: MySQL复制在循环binlog后closures 。

我们closures了mysql守护进程的fd 2,帮助信息写入了binlog.info。 这打破了主从复制。