Reputation: 599
I am working on a French chatbot using python. For a first text-to-speech attempt, I am using espeak with mbrola. I call it with subprocess :
from subprocess import run, DEVNULL
def speak(text):
command = ["espeak", "-vmb-fr1", text]
run(command, stderr=DEVNULL, stdout=DEVNULL)
speak("Bonjour.")
As you see, I'm sending stderr and stdout to /dev/null
When I run the program, It seems to work, espeak is speaking, but I get this :
*** Error in `mbrola': free(): invalid pointer: 0x08e3af18 ***
*** Error in `mbrola': free(): invalid pointer: 0x0988af88 ***
I think it is a C error in mbrola. I think I can't fix it. But it works, so I just want to mute the error. How can I do ? Is there a way ?
Edit, in response to abarnert :
When I redirect stdout and stderr by the shell (python myscript.py 2>&1 >/dev/null
), the message still show up.
Upvotes: 3
Views: 1526
Reputation: 365975
The root problem is that mbrola
/espeak
has a serious bug with memory allocation. If you haven't checked for a new version, and reported the bug to them, that's the first thing you should do.
These warnings are emitted by glibc's malloc checker, which is described in the mallopt
docs. If heap checking is enabled, every detected error with malloc
(and free
and related functions) will be printed out to stderr, but if it's disabled, nothing will be done. (Other possibilities are available as well, but that's not relevant here.)
According to the documentation, unless the program explicitly calls mallopt
, either setting the environment variable MALLOC_CHECK_
to 0 or not setting it at all should mean no malloc debug output. However, most of the major distros (starting with Debian) have long shipped a glibc
that's configured to default to 1 (meaning print the error message) instead of 0. You can still override this by explicitly setting MALLOC_CHECK_=0
.
Also, the documentation implies that malloc errors go to stderr
unless malloc_printerr
is replaced. But again, many distros do replace it with an intentionally-harder-to-ignore function that logs to the current process's tty if pretend and stderr if not. This is why it shows up even if you pipe espeak
's stderr to /dev/null, and your own program's as well.
So, to hide these errors, you can:
MALLOC_CHECK_
to 0 in espeak
, which will disable the checks.espeak
from opening a tty, which means the checks will still happen, but the output will have nowhere to go.Using setsid
, a tool that calls setsid
at the start of the new process, is one way to do the latter. Whether that's a good idea or not depends on whether you want the process to lead its own process group. You really should read up on what that means and decide what you want, not choose between the options because typing setsid
is shorter than typing MALLOC_CHECK_=0
.
And again, you really should check for a new version first, and report this bug upstream if they haven't fixed it yet.
Upvotes: 1
Reputation: 40013
Run it with setsid
(just add that string in front of the command and arguments). That will stop it from opening /dev/tty
to report the malloc errors. It will also prevent terminal signals, including SIGHUP
when the terminal is closed, from affecting the process, which may be a good or a bad thing.
Alternatively, set the environment variable LIBC_FATAL_STDERR_
to some nonempty string, with whose name I was able to find several similar questions.
Upvotes: 2