On Thu, Nov 11, 2010 at 04:59:01AM +0100, Enrico Forestieri wrote: > On Thu, Nov 11, 2010 at 02:57:48AM +0100, Vincent van Ravesteijn wrote: > > I'd like you to guide me a bit in with respect to using the pipes > > then. Detecting whether a pipe exists is indeed easy. However, I need > > to add some public functions to the Server interface that relays to > > LyXComm. Moreover, sending a new command over the pipe to the existing > > application needs some of the client code.. right ? > > > > If you can share your thoughts with me, I'd appreciate it. > > Please find attached a rough patch as proof of concept. It has to be > improved in many respects, but already does the job. I tested it on > both *nix and windows (with mingw) and it works for me. Simply setup > the lyxpipe and when you run lyx with a filename as argument, it > will be opened in already running instance.
Here is another somewhat polished version. -- Enrico
Index: src/LyX.cpp =================================================================== --- src/LyX.cpp (revisione 36244) +++ src/LyX.cpp (copia locale) @@ -380,7 +380,15 @@ int LyX::exec(int & argc, char * argv[]) FileName(package().temp_dir().absFileName() + "/lyxsocket"))); // Start the real execution loop. - exit_status = pimpl_->application_->exec(); + if (!theServer().isAlreadyRunning()) + exit_status = pimpl_->application_->exec(); + else if (!pimpl_->files_to_load_.empty()) { + vector<string>::const_iterator it = pimpl_->files_to_load_.begin(); + vector<string>::const_iterator end = pimpl_->files_to_load_.end(); + lyxerr << "The following files could not be loaded:" << endl; + for (; it != end; ++it) + lyxerr << *it << endl; + } prepareExit(); @@ -1236,6 +1244,13 @@ void dispatch(FuncRequest const & action } +vector<string> & theFilesToLoad() +{ + LASSERT(singleton_, /**/); + return singleton_->pimpl_->files_to_load_; +} + + BufferList & theBufferList() { LASSERT(singleton_, /**/); Index: src/Server.cpp =================================================================== --- src/Server.cpp (revisione 36244) +++ src/Server.cpp (copia locale) @@ -51,6 +51,7 @@ #include "support/debug.h" #include "support/FileName.h" +#include "support/filetools.h" #include "support/lassert.h" #include "support/lstrings.h" #include "support/os.h" @@ -60,6 +61,7 @@ #ifdef _WIN32 #include <QCoreApplication> #endif +#include <QThread> #include <cerrno> #ifdef HAVE_SYS_STAT_H @@ -140,6 +142,7 @@ LyXComm::LyXComm(string const & pip, Ser pipe_[i].handle = INVALID_HANDLE_VALUE; } ready_ = false; + used_running_instance_ = false; openConnection(); } @@ -515,8 +518,14 @@ void LyXComm::openConnection() return; } - // Check whether the pipe name is being used by some other program. + // Check whether the pipe name is being used by some other instance. if (!stopserver_ && WaitNamedPipe(inPipeName().c_str(), 0)) { + // Tell the running instance to load the files + if (loadFilesInOtherInstance()) { + used_running_instance_ = true; + pipename_.erase(); + return; + } lyxerr << "LyXComm: Pipe " << external_path(inPipeName()) << " already exists.\nMaybe another instance of LyX" " is using it." << endl; @@ -721,6 +730,7 @@ LyXComm::LyXComm(string const & pip, Ser : pipename_(pip), client_(cli), clientcb_(ccb) { ready_ = false; + used_running_instance_ = false; openConnection(); } @@ -798,6 +808,12 @@ int LyXComm::startPipe(string const & fi if (fd >= 0) { // Another LyX instance is using it. ::close(fd); + // Tell the running instance to load the files + if (loadFilesInOtherInstance()) { + used_running_instance_ = true; + pipename_.erase(); + return -1; + } } else if (errno == ENXIO) { // No process is reading from the other end. stalepipe = true; @@ -964,6 +980,47 @@ void LyXComm::send(string const & msg) #endif // defined (HAVE_MKFIFO) +namespace { + +struct Sleep : QThread { + static void millisec(unsigned long ms) + { + QThread::usleep(ms * 1000); + } +}; + +} // namespace anon + + +bool LyXComm::loadFilesInOtherInstance() +{ + int pipefd; + int loaded_files = 0; + FileName const pipe(inPipeName()); + vector<string>::iterator it = theFilesToLoad().begin(); + while (it != theFilesToLoad().end()) { + FileName fname = fileSearch(string(), os::internal_path(*it), + "lyx", may_not_exist); + if (fname.empty()) { + ++it; + continue; + } + // Wait a while to allow time for the other + // instance to reset the connection + Sleep::millisec(200); + pipefd = ::open(pipe.toFilesystemEncoding().c_str(), O_WRONLY); + if (pipefd < 0) + break; + string const cmd = "LYXCMD:pipe:file-open:" + + fname.absFileName() + '\n'; + ::write(pipefd, cmd.c_str(), cmd.length()); + ::close(pipefd); + ++loaded_files; + it = theFilesToLoad().erase(it); + } + return loaded_files > 0; +} + string const LyXComm::inPipeName() const { Index: src/Server.h =================================================================== --- src/Server.h (revisione 36244) +++ src/Server.h (copia locale) @@ -101,6 +101,9 @@ public: void read_ready(DWORD); #endif + /// Tell whether we asked another instance of LyX to open the files + bool deferredLoadingToOtherInstance() { return used_running_instance_; } + private: /// the filename of the in pipe std::string const inPipeName() const; @@ -114,6 +117,9 @@ private: /// Close pipes void closeConnection(); + /// Load files in another running instance of LyX + bool loadFilesInOtherInstance(); + #ifndef _WIN32 /// start a pipe int startPipe(std::string const &, bool); @@ -178,6 +184,9 @@ private: /// The client callback function ClientCallbackfct clientcb_; + + /// Did we defer loading of files to another instance? + bool used_running_instance_; }; @@ -197,6 +206,8 @@ public: ~Server(); /// void notifyClient(std::string const &); + /// + bool isAlreadyRunning() { return pipes_.deferredLoadingToOtherInstance(); } /// whilst crashing etc. void emergencyCleanup() { pipes_.emergencyCleanup(); } @@ -221,6 +232,9 @@ private: /// Implementation is in LyX.cpp Server & theServer(); +/// Implementation is in LyX.cpp +extern std::vector<std::string> & theFilesToLoad(); + } // namespace lyx Index: src/LyX.h =================================================================== --- src/LyX.h (revisione 36244) +++ src/LyX.h (copia locale) @@ -16,6 +16,8 @@ #include "support/strfwd.h" +#include <vector> + namespace lyx { class BufferList; @@ -126,6 +128,7 @@ private: friend FuncStatus getStatus(FuncRequest const & action); friend void dispatch(FuncRequest const & action); friend void dispatch(FuncRequest const & action, DispatchResult & dr); + friend std::vector<std::string> & theFilesToLoad(); friend BufferList & theBufferList(); friend Server & theServer(); friend ServerSocket & theServerSocket();