Chromium Code Reviews| Index: src/IceBrowserCompileServer.cpp |
| diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp |
| index 92d42e28e2aaa4efc13e9c37236669f10efd04d5..ba11e0125491c850abeaa4082f0b8726e75233ca 100644 |
| --- a/src/IceBrowserCompileServer.cpp |
| +++ b/src/IceBrowserCompileServer.cpp |
| @@ -18,6 +18,7 @@ |
| #include <cstring> |
| #include <irt.h> |
| #include <irt_dev.h> |
| +#include <pthread.h> |
| #include <thread> |
| #include "llvm/Support/QueueStreamer.h" |
| @@ -78,8 +79,7 @@ int onDataCallback(const void *Data, size_t NumBytes) { |
| char *onEndCallback() { |
| gCompileServer->endInputStream(); |
| gCompileServer->waitForCompileThread(); |
| - // TODO(jvoung): Also return an error string, and UMA data. |
| - // Set up a report_fatal_error handler to grab that string. |
| + // TODO(jvoung): Also return UMA data. |
| if (gCompileServer->getErrorCode().value()) { |
| const std::string Error = gCompileServer->getErrorStream().getContents(); |
| return strdup(Error.empty() ? "Some error occurred" : Error.c_str()); |
| @@ -100,15 +100,28 @@ std::unique_ptr<llvm::raw_fd_ostream> getOutputStream(int FD) { |
| new llvm::raw_fd_ostream(FD, CloseOnDtor, Unbuffered)); |
| } |
| +void fatalErrorHandler(void *UserData, const std::string &Reason, |
| + bool GenCrashDialog) { |
| + BrowserCompileServer *Server = |
| + reinterpret_cast<BrowserCompileServer *>(UserData); |
| + Server->setFatalError(Reason); |
| + // Only kill the current thread instead of the whole process. |
| + // We need the server thread to remain alive in order to respond with the |
| + // error message. |
| + // We could also try to pthread_kill all other worker threads, but |
| + // pthread_kill / raising signals is not supported by NaCl. |
| + // We'll have to assume that the worker/emitter threads will be well behaved |
| + // after a fatal error in other threads, and either get stuck waiting |
| + // on input from a previous stage, or also call report_fatal_error. |
| + pthread_exit(0); |
| +} |
| + |
| } // end of anonymous namespace |
| BrowserCompileServer::~BrowserCompileServer() {} |
| void BrowserCompileServer::run() { |
| gCompileServer = this; |
| - // TODO(jvoung): make a useful fatal error handler that can |
| - // exit all *worker* threads, keep the server thread alive, |
| - // and be able to handle a server request for the last error string. |
| getIRTInterfaces(); |
| gIRTFuncs.serve_translate_request(&SubzeroCallbacks); |
| } |
| @@ -129,12 +142,33 @@ void BrowserCompileServer::getParsedFlags(uint32_t NumThreads, int argc, |
| } |
| bool BrowserCompileServer::pushInputBytes(const void *Data, size_t NumBytes) { |
| + // If there was an earlier error, do not attempt to push bytes to |
| + // the QueueStreamer. Otherwise the thread could become blocked. |
| + if (HadError.load()) |
| + return true; |
| return InputStream->PutBytes( |
| const_cast<unsigned char *>( |
| reinterpret_cast<const unsigned char *>(Data)), |
| NumBytes) != NumBytes; |
| } |
| +void BrowserCompileServer::setFatalError(const IceString &Reason) { |
| + HadError.store(true); |
| + Ctx->getStrError() << Reason; |
|
Jim Stichnoth
2015/06/03 16:16:01
I was wondering about using OstreamLocker for mult
jvoung (off chromium)
2015/06/04 00:33:16
Hmm good point. I forgot about OstreamLocker, but
|
| + // Make sure that the QueueStreamer is not stuck by signaling an early end. |
| + InputStream->SetDone(); |
| +} |
| + |
| +ErrorCode &BrowserCompileServer::getErrorCode() { |
| + if (HadError.load()) { |
| + // HadError means report_fatal_error is called. Make sure that the |
| + // LastError is not EC_None. We don't know the type of error so |
| + // just pick some error category. |
| + LastError.assign(EC_Translation); |
| + } |
| + return LastError; |
| +} |
| + |
| void BrowserCompileServer::endInputStream() { InputStream->SetDone(); } |
| void BrowserCompileServer::startCompileThread(int ObjFD) { |
| @@ -150,6 +184,7 @@ void BrowserCompileServer::startCompileThread(int ObjFD) { |
| &ErrorStream->getStream(), ELFStream.get(), |
| Flags)); |
| CompileThread = std::thread([this]() { |
| + llvm::install_fatal_error_handler(fatalErrorHandler, this); |
| Ctx->initParserThread(); |
| this->getCompiler().run(ExtraFlags, *Ctx.get(), |
| // Retain original reference, but the compiler |