昨天遇到collectd exec插件的bug,顺便发现他们不按套路出牌啊

先说症状:

collectd exec插件调用的几个外部脚本,其中总会随机有一个缺少COLLECTD_HOSTNAME和COLLECTD_INTERVAL环境变量。

搜了一下是这个bug https://github.com/collectd/collectd/issues/3041

然后我好奇啊,就读了一下修改前后的代码,发现collectd不按套路出牌。

带有bug的版本:

先setenv()设置主进程自己的环境变量,然后尝试fork(),如果成功,在子进程里execvp();主进程重新unsetenv()恢复主进程自己的环境变量。在多个exec密集执行的时候,都会访问主进程的环境变量,会有race condition,偶尔会发生前一个exec插件刚unsetenv()然后后一个exec插件开始fork()的情况,丢失环境变量。

修复后的版本:

先fork(),在子进程里准备环境变量数组,尝试execvpe()带签署环境变量数组作为参数,执行新进程(execvpe()为GNU专有扩展),或者先设置extern char **environ指针指向准备好的数组,然后execvp()执行新进程直接继承。

别人家套路:

先准备环境变量数组,然后fork(),在子进程里execve()并使用前述环境变量数组作为参数。

This entry was posted in 默认分类 and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.