X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FServer.cpp;h=d7a2e2514c285a26a533bfa67b39ac6bf79c6b5e;hb=70a24259f8e3eb75677178ef5e28ecbb51c2935b;hp=286be5d4da9cea891424cd0257d0d686ccb9d71b;hpb=b89cc942eb458284f40f4d4e7db58890c3288979;p=lyx.git diff --git a/src/Server.cpp b/src/Server.cpp index 286be5d4da..d7a2e2514c 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -3,7 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author Angus Leeming * \author John Levon @@ -40,15 +40,15 @@ #include #include "Server.h" -#include "support/debug.h" #include "FuncRequest.h" #include "LyXAction.h" #include "LyXFunc.h" + #include "frontends/Application.h" +#include "support/debug.h" #include "support/FileName.h" #include "support/lstrings.h" -#include "support/lyxlib.h" #include @@ -72,7 +72,7 @@ namespace lyx { #if !defined (HAVE_MKFIFO) // We provide a stub class that disables the lyxserver. -LyXComm::LyXComm(std::string const &, Server *, ClientCallbackfct) +LyXComm::LyXComm(string const &, Server *, ClientCallbackfct) {} void LyXComm::openConnection() @@ -107,7 +107,7 @@ void LyXComm::send(string const & msg) #else // defined (HAVE_MKFIFO) -LyXComm::LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb) +LyXComm::LyXComm(string const & pip, Server * cli, ClientCallbackfct ccb) : pipename_(pip), client_(cli), clientcb_(ccb) { ready_ = false; @@ -178,13 +178,39 @@ void LyXComm::closeConnection() int LyXComm::startPipe(string const & file, bool write) { + static bool stalepipe = false; FileName const filename(file); - if (::access(filename.toFilesystemEncoding().c_str(), F_OK) == 0) { - lyxerr << "LyXComm: Pipe " << filename << " already exists.\n" - << "If no other LyX program is active, please delete" - " the pipe by hand and try again." << endl; - pipename_.erase(); - return -1; + if (filename.exists()) { + if (!write) { + // Let's see whether we have a stale pipe. + int fd = ::open(filename.toFilesystemEncoding().c_str(), + O_WRONLY | O_NONBLOCK); + if (fd >= 0) { + // Another LyX instance is using it. + ::close(fd); + } else if (errno == ENXIO) { + // No process is reading from the other end. + stalepipe = true; + LYXERR(Debug::LYXSERVER, + "LyXComm: trying to remove " + << filename); + filename.removeFile(); + } + } else if (stalepipe) { + LYXERR(Debug::LYXSERVER, "LyXComm: trying to remove " + << filename); + filename.removeFile(); + stalepipe = false; + } + if (filename.exists()) { + lyxerr << "LyXComm: Pipe " << filename + << " already exists.\nIf no other LyX program" + " is active, please delete the pipe by hand" + " and try again." + << endl; + pipename_.erase(); + return -1; + } } if (::mkfifo(filename.toFilesystemEncoding().c_str(), 0600) < 0) { @@ -252,6 +278,12 @@ void LyXComm::read_ready() int const charbuf_size = 100; char charbuf[charbuf_size]; + // As O_NONBLOCK is set, until no data is available for reading, + // read() doesn't block but returns -1 and set errno to EAGAIN. + // After a client that opened the pipe for writing, closes it + // (and no other client is using the pipe), read() would always + // return 0 and thus the connection has to be reset. + errno = 0; int status; // the single = is intended here. @@ -273,12 +305,13 @@ void LyXComm::read_ready() clientcb_(client_, cmd); //\n or not \n? } - } - if (errno == EAGAIN) { - errno = 0; - return; - } - if (errno != 0) { + } else { + if (errno == EAGAIN) { + // Nothing to read, continue + errno = 0; + return; + } + // An error occurred, better bailing out LYXERR0("LyXComm: " << strerror(errno)); if (!read_buffer_.empty()) { LYXERR0("LyXComm: truncated command: " << read_buffer_); @@ -288,8 +321,9 @@ void LyXComm::read_ready() } } - // The connection gets reset in errno != EAGAIN - // Why does it need to be reset if errno == 0? + // The connection gets reset when read() returns 0 (meaning that the + // last client closed the pipe) or an error occurred, in which case + // read() returns -1 and errno != EAGAIN. closeConnection(); openConnection(); errno = 0; @@ -344,7 +378,7 @@ void ServerCallback(Server * server, string const & msg) server->callback(msg); } -Server::Server(LyXFunc * f, std::string const & pipes) +Server::Server(LyXFunc * f, string const & pipes) : numclients_(0), func_(f), pipes_(pipes, this, &ServerCallback) {} @@ -495,7 +529,7 @@ void Server::callback(string const & msg) } -// Send a notify messge to a client, called by WorkAreaKeyPress +// Send a notify message to a client, called by WorkAreaKeyPress void Server::notifyClient(string const & s) { pipes_.send("NOTIFY:" + s + "\n");