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();