【问题标题】:What happens if you ignore a X11 BadWindow error?如果您忽略 X11 BadWindow 错误会发生什么?
【发布时间】:2014-01-19 05:07:38
【问题描述】:

我有一个 1990 年代早期编写的遗留 Motif 应用程序(我无法在 QT 中重写 UI,甚至无法在不经过耗时的安全评估的情况下广泛修改应用程序)。这个应用程序曾经在 AIX 上运行,它在密集使用的情况下连续运行了数周,并且非常稳定。我们现在已经将它移植到 Linux 上。在长时间的持续 Beta 测试期间,该应用大约每周崩溃一次,并显示以下消息。

请求失败的错误:BadWindow(无效的窗口参数)
请求失败的主要操作码:4 (X_DestroyWindow)

我后来了解到可以使用自定义 X11 错误处理程序(默认 X11 错误处理程序仅打印错误消息并退出)忽略这些错误,如下所述:

http://motifdeveloper.com/tips/tip29.html

我已经实现了一个自定义 X11 错误处理程序,它会忽略该文章中描述的 BadWindow 错误。所以我的问题是:比我更了解 X11 开发和 X 服务器内部工作原理的人能否告诉我是否真的可以像那样忽略 BadWindow 错误?

附注 我将尝试通过在同步模式下运行我们的应用程序来进一步调试它,但这很慢,因为我无法按需重现此错误。任何有关调试 BadWindow 错误的提示也将不胜感激。

【问题讨论】:

  • 这取决于你所说的“可以”是什么意思。它会断开您与互联网的连接并吃您的午餐吗?可能不是。应用程序会像什么都没发生一样工作吗?可能不是。该错误本身并不致命,但它是应用程序逻辑中某些错误的表现,那个错误很可能很严重
  • 到目前为止,我没有看到任何不良影响,但我将对其进行详尽的测试。此外,这只发生在 Linux 上,而不是 AIX 上,并且 UI 多年来没有发生重大变化。

标签: linux error-handling x11 aix motif


【解决方案1】:

如果您的程序由单个进程(与 X 显示器的单个连接)组成,那么此错误几乎总是反映程序中的错误。

要知道的秘密是如何调试它。因为 Xlib 是异步的,XDestroyWindow() 将触发并忘记,窗口上的一些后销毁操作也可能触发并忘记,并且您在将来的某个时间(在其他一些不相关的 X 调用期间)会收到错误。这意味着来自 X 错误的堆栈跟踪是没有意义的,并且很难调试。

要解决此问题,请调用 XSynchronize(dpy, True) 以强制所有调用同步。这将使应用程序变慢,因此不要将其留在生产中。 http://www.x.org/releases/X11R7.6/doc/man/man3/XSynchronize.3.xhtml

但是在同步模式下,如果 Xlib 调用使用了错误的窗口,它将立即失败。因此,您可以设置调试断点,例如在错误处理函数上,并获得有意义的回溯。这应该会告诉您是哪个 Xlib 调用导致了问题 - 并且希望它是一个小部件的双重删除、使用已破坏的小部件还是什么的。

如果您的应用程序确实有多个进程或多个显示连接,例如在窗口管理器中,那么BadWindow 可能是不可避免的(如果您试图弄乱另一个应用程序的窗口,那么不可避免地会出现竞争另一个应用程序的窗口可能会被破坏)。在这种情况下,忽略BadWindow 是正确的解决方案,尽管最佳做法是仅在那些已知会触发它的调用期间忽略它,因此您仍然会遇到可能是错误的错误。一个常见的习惯用法是实现一个error_trap_push()/error_trap_pop(),它只是安装和卸载忽略错误的错误处理程序。当您触摸可能会在您无法控制的情况下被删除的外部窗口时,推送错误陷阱。

【讨论】:

  • 非常感谢您的回答。我会尝试同步运行应用程序,对其进行测试,看看会显示什么。
【解决方案2】:

这看起来像是一个按钮(或类似的 UI 元素)被多次删除。通常,按钮被实现为专用窗口,其中发出按钮图形,这样您就可以简单地将回调处理程序与关联窗口中的单击事件联系起来。

该错误表明您的程序已尝试删除一个不存在的窗口 ID,而发生这种情况的最简单方法确实是它已被删除两次(或者,某处为某个 UI 元素记录的 ID 发生了更改)。

此时,您不想忽略错误,您希望获得足够的日志记录以找出应用程序的问题所在。

【讨论】:

  • 让我感到困扰的是,这些错误并没有发生在 AIX 上,只发生在 Linux 上,所以我认为这一定是 X 服务器中的实现差异。
  • @osxnerd 也可能是底层库的差异。最坏的情况是,您最终可能会得到认为它具有可点击小部件的 UI,但实际上它们已被删除,从而使最终用户无法使用应用程序。因此,请使用足够的调试日志记录来发现错误并消除它。
  • 如果错误是间歇性的,它可能是某种竞争条件。平台中各种随机不相关的差异可能会导致触发或不触发,因为它们可能会影响时间。也可能是不同的 Motif 行为或其他东西,或者如您所说的不同的 X 服务器。
【解决方案3】:

在这种情况下,错误告诉您您的程序请求销毁一个不存在的窗口 id。如果您忽略它,那么您可能会泄漏您真正打算破坏的任何窗口;或者您可能只是试图两次销毁相同的窗口 id,但什么都不会改变。如果不追查为什么您的程序使用无效 id 调用 XDestroyWindow 的根本原因,很难说如果您忽略它会发生什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多