Dealing with llvm::errs() and friends in dynamic libs on Windows

Hello,

outs() and errs() are routinely used around llvm and cannot really be disabled. It would seem that in certain types of Windows applications, stderr and stdout are not opened by default, which is an assumption of llvm.

This leaves errs() and outs() with an error code, because writing calls will fail due to invalid fd handles. Thus, when an llvm lib is unloaded, it will terminate the entire process due to a non-zero EC in ~raw_fd_ostream() that calls report_fatal_error().

It doesn’t help that outs(), errs() etc. are not returning raw_fd_ostream, so you cannot clear the error codes manually (without dynamic_cast):

struct LLVMCleanup
{
~LLVMCleanup()
{
for (auto stream : {&llvm::errs(), &llvm::outs()})
{
if (auto fdStream = dynamic_castllvm::raw_fd_ostream*(stream))
fdStream->clear_error();
}
}
};

Above is my currently working fix (if I sprinkle it in enough places) but it is a pretty fragile solution. Is there some special initialization or handling that I’m missing? My program is itself a dynamic lib, so I don’t control state of stderr or stdout. I would rather not terminate my host process because diagnostic prints failed.

Thanks - and regards,
Janus

I think the easiest way for you to deal with this will be to redirect FDs 1 and 2 to the NUL device, or to a pipe or wherever you’d like LLVM or any other third party libraries to send their output.

Hello,

outs() and errs() are routinely used around llvm and cannot really be disabled. It would seem that in certain types of Windows applications, stderr and stdout are not opened by default, which is an assumption of llvm.

LLVM libraries shouldn't write to outs() unless you explicitly request it; at best it points somewhere useless, at worst it'll corrupt output written to stdout. We consider it a bug if this happens. (Quickly grep'ing, it looks like there's a bug where lib/MC/MCParser/AsmParser.cpp will write to outs() when given a ".print" directive, but I'm guessing you're very unlikely to run into that.)

The default error reporting mechanism for errors compiling unsupported LLVM IR constructs writes to errs(), but you can override that by calling LLVMContext::setDiagnosticHandler(). Otherwise, we consider it a bug if LLVM libraries write to errs() without an explicit request. (There's a lot of code which writes to errs, but it's diagnostics which should not run by default.)

Please report a bug or send a patch if you're running into issues with some specific construct that causes LLVM to write to outs() or errs() incorrectly.

This leaves errs() and outs() with an error code, because writing calls will fail due to invalid fd handles. Thus, when an llvm lib is unloaded, it will terminate the entire process due to a non-zero EC in ~raw_fd_ostream() that calls report_fatal_error().

This seems a bit unfriendly, particularly since the error gets delayed far past the point it would actually be useful, but it probably indicates something else is going wrong. Even on Unixy systems where stdout and stderr are usually open, they often don't point anywhere useful for GUI programs.

-Eli