Stlink: st-util 应该在 LIBUSB_ERROR_NO_DEVICE 上退出

创建于 2019-03-17  ·  12评论  ·  资料来源: stlink-org/stlink

当我第一次拔下 USB 调试器,然后尝试通过 GDB 发出命令时,st-util 非常迅速地给出以下错误:

  core status: unknown
[!] send_recv send request failed: LIBUSB_ERROR_NO_DEVICE                      
[!] send_recv STLINK_DEBUG_GETSTATUS
  core status: unknown
[!] send_recv send request failed: LIBUSB_ERROR_NO_DEVICE                      
[!] send_recv STLINK_DEBUG_GETSTATUS
  core status: unknown
[!] send_recv send request failed: LIBUSB_ERROR_NO_DEVICE                      
[!] send_recv STLINK_DEBUG_GETSTATUS
  core status: unknown
[!] send_recv send request failed: LIBUSB_ERROR_NO_DEVICE                      
[!] send_recv STLINK_DEBUG_GETSTATUS
  core status: unknown
2019-03-17T14:26:42 ERROR src/flash_loader.c: flash loader run error           
2019-03-17T14:26:42 ERROR src/common.c: stlink_flash_loader_run(0x8000000) failed! == -1

从而几乎 100% 地占用 CPU。 这会导致严重的时间浪费(重新启动虚拟机等)。

这种错误信息是很正常的。 但是, stutil应该在出现此错误时立即退出,以便我可以通过重新启动stutil或采取其他一些措施来处理其余的问题。

bufixed componenst-util componenstlink-lib dependenclibusb errogdb-server staturesolved

所有12条评论

我认为stlink应该在此时终止: https :

我认为stlink应该在此时终止:

https://github.com/texane/stlink/blob/df3c2b02867db03fb82f6faaad71300398965e85/src/usb.c#L54

是的,我认为您是对的,应该适当检查对 libusb 的调用。 如果你愿意,你可以修补并发送 PR。 对于在 usb.c 文件中对 libusb 的其他调用也应该这样做。 感谢举报!

如果你愿意,你可以修补并发送 PR。

我喜欢。 但是,我不确定我是否了解项目结构,因此简单的exit(1)在这里是否足够。

对于在 usb.c 文件中对 libusb 的其他调用也应该这样做。

我可能不太明白这一点。 您的意思是“ send_recv使应用程序在返回-1地方终止”?

我在 PR 中发表了评论,当调用 libusb 时,还有更多地方可能会出错。

该项目按以下方式组织:

  • libstlink(usb.c 是它的一部分,永远不应该在库中使用 exit)库的文件位于 src 文件夹中,最重要的是 usb.c 和 common.c(当然还有 flash_loader.c)
  • st-util位于 src/gdbserver
  • st-info位于 src/tools/info.c
  • st-flash位于 src/tools/flash.c

我认为这可能与 #888 和 #445 有关。
@ceremcem@rewolff :一起讨论这个想法怎么样?

@chenguokai :你知道如何在这里进行吗?

无法重现这种情况。
我在我的 macOS 机器上遵循了这个过程。 出现错误消息,但没有进入任何死循环的迹象。
image
image

编辑:我在main函数上设置断点并拔下 st-link 后发出命令n

确实存在程序应该退出而不是无限重试发送或接收数据包的问题。

https://github.com/texane/stlink/blob/0082e488579077762627dba2cee54ffca64dad17/src/gdbserver/gdb-server.c#L1121

这个函数调用没有返回一个合适的值来结束 while(1) 循环。 问题可能出在函数或 while(1) 机制内部。

lldb检查错误处理过程后,我大概找出了故障代码。

https://github.com/texane/stlink/blob/bf840a1ae82ffc3ef9929f243bb8050d6856f698/src/gdbserver/gdb-server.c#L1448

_stlink_usb_step遇到最初由 libusb 调用失败触发的错误时,它返回一个非零返回值(在这种情况下为 -1)。 但是,gdb-server 中的 recv-handle-send 循环不处理此返回值:

https://github.com/texane/stlink/blob/bf840a1ae82ffc3ef9929f243bb8050d6856f698/src/gdbserver/gdb-server.c#L1119

我提出了两种可能的交易策略:

公共部分:检查switch case中stlink_step的返回值。

  1. 如果出现任何错误,请尝试通知 GDB 并退出。
  2. 限制次数重做该函数调用,如果仍然失败,通知 GDB 并退出,否则继续。

分析:

选项 1 是可以接受的,因为我们无法预测通信错误后会发生什么。 缺点是 st-util 在某些不稳定的 USB 端口或类似的东西上可能会更频繁地失败。
选项 2 会给不稳定的设备另一个机会,但可能会导致数据包重复,这使得调试更加不可预测。

谢谢详细分析。 我更喜欢这里的选项 1。 如果人们遇到与特定本地硬件不稳定性相关的问题,我们无论如何也无能为力,这也不是 stlink 工具应该考虑的。 我们对调试做出任何妥协似乎更重要。 你能马上解决这个问题吗?

我将检查 gdb 的文档以正确发送数据包。 我想不是太难。
完成后,我会提出一个PR。

我没有说,但我选择了选项 2。但是在你的解释之后:你是对的。 你让我信服了:除非有充分的理由相信错误是暂时的,否则应该立即将错误视为致命错误。

在没有通知用户的情况下重试会导致突然的意外。 假设传输位的 1/100 或 1/1000 被损坏(无论级别如何)。 如果这导致命令在 99% 的时间内“无效”,那么在这种情况下,用户在获得导致问题的静默数据损坏之前,平均会收到大量警告(即 stlink 突然退出),说明他的硬件不稳定。 ...

“简单的出路”就是“退出()”。 这将突然关闭与 gdb 的连接,它会足够优雅地处理它。

基本功能在 stm32f401 板的 PR 下运行良好。
在我的本地测试期间解决了死循环。 现在 st-util 将退出。 gdb 将收到失败回复并断开连接。

此页面是否有帮助?
0 / 5 - 0 等级