我们开始调查为何重新加载Apache会进入libgomp的这段代码 。 所以显然 , 重载Apache会导致mod_php调用一个名为Imagick的模块 。 Imagick是什么?它是一个使用ImageMagick库来创建和修改图片的PHP扩展 。
怀疑
似乎关闭Imagick就可以避免使用libgomp , 这样就不会遇到最大线程数的问题了 。 而且只需要设置一个环境变量即可 。 似乎这个方案非常安全 , 但我们依然有一个最大的疑问:
- 为什么会在1月1日发生?而且这么大的范围 , 真的是偶然吗?
- 为什么用了这么多年都没事儿?会不会因为是某个更新的原因?
但这些都没有任何帮助 。 我们甚至怀疑过Apache的最大uptime 。
最后我们检查了Imagick的更新日志 , 发现了这个:
“多个修改来减少GOMP段错误的发生 , 包括:
- 在关闭过程中 , 如果可能 , 则调用omp_pause_resource_all
- 增加了 `imagick.shutdown_sleep_count` (默认10)和`imagick.set_single_thread`(默认On) 。两者都可以减少关闭时的段错误 。”
灵光乍现
在搜索了更多奇怪的东西后 , 我们想看看一月份有没有人遇到这个问题 。
文章图片
第一篇文章正是解开这一切的钥匙!
文章图片
突然想到……要是线程键从来没有被释放 , 会怎样?有可能吗?因为从部署依赖就从来没有发生过这个问题……所以我们重新计算了一下 , 1024个键 , 如果每天早上重新加载 , 就需要两年零10个月才会超过1024次重新加载 。 如果过去1024天内每天早上都分配一个线程键 , 而这个键从未被释放的话……
终于看到了一丝曙光 。 我们终于找到了重现该问题的方法 。 我们做了一个测试环境 , 用同样的服务器配置 , 然后简单地运行这个脚本 。
Apache在重新加载了1024次以后 , libgomp就报错了 。 现在所有问题都得到了解答 。
来看看能否通过增加环境变量MAGICK_THREAD_LIMIT(新版Imagick是OMP_THREAD_LIMIT) 。 很不幸 , 问题依旧 。 所以下一步就是更新Imagick版本到一个修正了该问题的版本(v3.5.0+) 。 很幸运 , 更新之后重新加载数千次都不会出问题 。
检查
还有个未解决的问题:新版Imagick有没有删除这个键?为了解答这个疑问 , 我们使用了一个工具:ltrace这个工具可以截获并记录程序运行的特定命令 。 我们首先在旧版本的Imagick(v.3.4.4)的服务器上运行ltrace:
-L告诉ltrace忽略默认的过滤器 , 以降低噪声 。
-c会在末尾汇总所有结果 。 而 /usr/sbin/apache2 -k graceful相当于systemctlreload apache 。
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
