3

我正在使用 python 开发一个法语聊天机器人。对于第一次文本到语音的尝试,我正在使用 espeak 和 mbrola。我用 subprocess 调用它:

from subprocess import run, DEVNULL

def speak(text):
    command = ["espeak", "-vmb-fr1", text]
    run(command, stderr=DEVNULL, stdout=DEVNULL)

speak("Bonjour.")

如您所见,我将 stderr 和 stdout 发送到/dev/null

当我运行程序时,它似乎可以工作,espeak 正在说话,但我得到了这个:

*** Error in `mbrola': free(): invalid pointer: 0x08e3af18 ***
*** Error in `mbrola': free(): invalid pointer: 0x0988af88 ***

我认为这是 mbrola 中的 C 错误。我想我无法修复它。但它有效,所以我只想忽略错误。我能怎么做 ?有办法吗?


编辑,以回应abarnert

当我通过 shell ( python myscript.py 2>&1 >/dev/null) 重定向 stdout 和 stderr 时,消息仍然显示。

  • 发行版:Debian 9.3
  • glibc 版本:2.24
4

2 回答 2

2

运行它setsid(只需在命令和参数前面添加该字符串)。这将阻止它打开/dev/tty以报告 malloc 错误。它还将防止终端信号,包括SIGHUP终端关闭时,影响进程,这可能是好事也可能是坏事。

或者,将环境变量设置LIBC_FATAL_STDERR_一些非空字符串,我可以通过它的名字找到几个 类似的 问题

于 2018-04-28T03:13:18.970 回答
1

根本问题是mbrola/espeak有一个严重的内存分配错误。如果您还没有检查新版本并向他们报告错误,那是您应该做的第一件事。

这些警告由 glibc 的 malloc 检查器发出,mallopt文档中对此进行了描述。如果启用堆检查,每个检测到的mallocfree以及相关函数)错误都将打印到 stderr,但如果它被禁用,则不会执行任何操作。(其他可能性也是可用的,但这在这里不相关。)

根据文档,除非程序显式调用 ,否则将mallopt环境变量设置MALLOC_CHECK_为 0 或根本不设置它应该意味着没有 malloc 调试输出。但是,大多数主要发行版(从 Debian 开始)早就发布了一个glibc配置为默认值 1(意味着打印错误消息)而不是 0。您仍然可以通过显式设置来覆盖它MALLOC_CHECK_=0

此外,文档暗示 malloc 错误去stderr除非malloc_printerr被替换。但是同样,许多发行版确实将其替换为故意难以忽略的功能,如果假装则记录到当前进程的 tty,如果不是则记录到 stderr。这就是为什么即使您通过管道espeak将 的 stderr 传输到 /dev/null 以及您自己的程序也会显示它的原因。

因此,要隐藏这些错误,您可以:

  • 在 中将环境变量设置MALLOC_CHECK_为 0 espeak,这将禁用检查。
  • 防止espeak打开 tty,这意味着检查仍然会发生,但输出将无处可去。

使用在新进程开始时setsid调用的工具是完成后者的一种方法。setsid这是否是一个好主意取决于您是否希望流程领导自己的流程组。您真的应该阅读这意味着什么并决定您想要什么,而不是在选项之间进行选择,因为打字setsid比打字短MALLOC_CHECK_=0

再说一次,你真的应该先检查一个新版本,如果他们还没有修复它,就向上游报告这个错误。

于 2018-04-28T17:13:11.877 回答