我的公司销售具有许多可执行文件的基于Linux的设备。这些应用程序之一每隔几天就会挂在我们产品的最新版本中。
我们正在使用glibc 2.19和gcc 4.8.3以及Linux内核版本3.16.38。我们正在为x86_64构建。
我们的glibc版本非常旧,我们应该在一年前用以下修复程序对其进行修补: 错误#12926:getaddrinfo()/ make_request()永远旋转(https://sourceware.org/bugzilla/show_bug.cgi?id=12926)
我们的工具的维护者发誓我们正在使用的工具带有补丁的glibc。但是,还有其他失败的可能性,例如由于某些原因,我们的构建可能会选择其他glibc。
在构建计算机上,我们保存了应用程序可执行文件和共享库二进制文件的未压缩版本,以便以后在调试核心文件时使用。
我通过登录具有挂起的应用程序的设备并向进程发送SIGILL生成了一些核心文件。
核心文件似乎表明我们在getaddrinfo()中遇到了挂起,并且堆栈跟踪看起来像我们在修补glibc之前获得的那样。使用最新部署的版本的最新核心文件中的示例:
Thread #18 1456 (Suspended : Container)
recvmsg() at 0x7f1fa276c17d
make_request() at 0x7f1fa278695d
__check_pf() at 0x7f1fa2786e54
getaddrinfo() at 0x7f1fa2759501
Thread #16 1454 (Suspended : Container)
__lll_lock_wait_private() at 0x7f1fa277777b
_L_lock_443() at 0x7f1fa2786f4d
__check_pf() at 0x7f1fa2786d05
getaddrinfo() at 0x7f1fa2759501
我希望能够验证我们已部署的发行可执行文件正在执行的getaddrinfo()版本:已修补还是未修补。在我的个人开发工具箱上执行此操作无济于事,因为那只会验证我自己的工具链/构建环境。我可以用已部署的发行版二进制文件执行此操作吗?
编辑:我忘了提到我们静态链接。
编辑2:关于静态链接,我错了。我们过去经常静态链接几乎所有内容,但不再与系统库静态链接。感谢那些指出这一点的人。
答案 0 :(得分:2)
bug 12926中的更改仅是诊断辅助。如果需要它们,您的应用程序中将有一个文件描述符竞赛。结果可能更容易找到,但这还不清楚。但是与文件描述符竞争条件有关的应用程序错误肯定需要独立修复。
glibc本身存在一个错误,可能会导致文件描述符重用不正确,bug 15946。此修补程序比错误12926中的更改重要得多。错误15946可以以多种不同的方式实现,而错误12926中的挂起是一种可能性。
请注意,错误15946的更改会影响libresolv
,默认情况下该链接是动态链接的,即使应用程序是静态链接的也是如此。除非您覆盖glibc的构建设置并同样静态地链接libresolv
或安排搜索路径以使您运送的libresolv
的副本被拾取,否则仍必须修复系统glibc。
一旦下一次挂起,您可以尝试查看/proc/PID/fd
或lsof -p
的输出。有时,文件描述符后面的文件或套接字可以为您提供它的来源线索,并查明应用程序内部不正确的文件描述符重用。
答案 1 :(得分:1)
我们的工具的维护者发誓我们正在使用的工具带有补丁的glibc。
除非您进行静态链接(根据堆栈跟踪中的0x7f1fa276c17d
地址,您不要判断),否则您的跨工具中的GLIBC版本可能没有” 问题。
但是,还有其他失败的可能性,例如由于某些原因,我们的构建可能会选择其他glibc。
通常,您将从系统中获取GLIBC,并且如果未对GLIBC进行类似的修补,则预期仍然会存在该错误。这就是动态链接的工作方式。
可以使用与系统一并安装的自己的GLIBC。但是,这不是entirely trivial。