最近发现在lua中通过os.execute执行系统shell脚本时,偶尔会发生错误退出,最后发现是bash本身的问题。
对于下面的shell脚本
1 |
|
bash执行时会发生段错误
1 |
|
bash执行shell脚本时,默认使用255的文件描述符打开/读取当前执行的这个shell脚本。这里将11-254,256-274这些文件描述符都使用了,然后调用exec 255>&-
操作可以关闭代表当前shell脚本的文件描述符。这时便会发生错误。
看了下bash的实现,原来bash中操作的文件描述符,bash会为其创建一个buffer缓冲区,放在一个数组buffers
中。在shell脚本中调用exec
关闭文件描述符时, 如果要关闭的文件描述符恰好指向当前执行的shell脚本时,bash会复制出一个新的文件描述符,将旧的关闭,之后用新的文件描述符读取shell脚本。对于这个新的文件描述符如果过大的话,会超过buffers
数组的大小,导致内存访问越界。
bash的实现代码如下所示
1 |
|
buffers
是一个buffer
数组,数组的索引是文件描述符,值为对应的缓冲区。这里的nfd
是复制产生的新的文件描述符,buffers[nfd]
这里没有判断buffers数组的长度,一旦nfd
过大,就会发生数组越界访问。
貌似bash 4.4中已经修复了这个问题,通过比较nfd
与buffers
数组的长度避免数组越界。相应代码变成下面这样。
1 |
|