1 #include "socketexternalcom.h"
2
3 #include <QLocalServer>
4 #include <QLocalSocket>
5 #include <QSharedMemory>
6
7 #ifdef Q_OS_UNIX
8 #include <signal.h>
9 #include <unistd.h>
10 #endif
11
12 #include "log.h"
13
14 static const char* GLOG_SERVICE_NAME = "org.bonnefon.glogg";
15
16 #ifdef Q_OS_UNIX
17 QSharedMemory* g_staticSharedMemory = nullptr;
18
terminate(int signum)19 void terminate(int signum)
20 {
21 if (g_staticSharedMemory) {
22 delete g_staticSharedMemory;
23 }
24 ::exit(128 + signum);
25 }
26
setCrashHandler(QSharedMemory * memory)27 void setCrashHandler(QSharedMemory* memory)
28 {
29 g_staticSharedMemory = memory;
30
31 // Handle any further termination signals to ensure the
32 // QSharedMemory block is deleted even if the process crashes
33 signal(SIGSEGV, terminate);
34 signal(SIGABRT, terminate);
35 signal(SIGFPE, terminate);
36 signal(SIGILL, terminate);
37 signal(SIGINT, terminate);
38 signal(SIGTERM, terminate);
39 }
40
41 #endif
42
SocketExternalInstance()43 SocketExternalInstance::SocketExternalInstance()
44 : ExternalInstance(), memory_(new QSharedMemory(GLOG_SERVICE_NAME) )
45 {
46 if ( !memory_->attach( QSharedMemory::ReadOnly ) ) {
47 LOG( logERROR ) << "attach failed!";
48 throw CantCreateExternalErr();
49 }
50
51 #ifdef Q_OS_UNIX
52 // Handle any further termination signals to ensure the
53 // QSharedMemory block is deleted even if the process crashes
54 setCrashHandler(memory_);
55 #endif
56 }
57
loadFile(const QString & file_name) const58 void SocketExternalInstance::loadFile(const QString &file_name) const
59 {
60 QLocalSocket socket;
61 socket.connectToServer(GLOG_SERVICE_NAME);
62 if (!socket.waitForConnected(1000)) {
63 LOG( logERROR ) << "Failed to connect to socket";
64 return;
65 }
66
67 socket.write(file_name.toUtf8());
68 if (!socket.waitForBytesWritten(1000)) {
69 LOG( logERROR ) << "Failed to send filename";
70 }
71
72 socket.close();
73 }
74
getVersion() const75 uint32_t SocketExternalInstance::getVersion() const
76 {
77 return *reinterpret_cast<uint32_t*>(memory_->data());
78 }
79
SocketExternalCommunicator()80 SocketExternalCommunicator::SocketExternalCommunicator()
81 : ExternalCommunicator()
82 , memory_(new QSharedMemory(GLOG_SERVICE_NAME))
83 , server_(new QLocalServer)
84 {}
85
~SocketExternalCommunicator()86 SocketExternalCommunicator::~SocketExternalCommunicator()
87 {
88 delete memory_;
89 server_->close();
90 delete server_;
91 }
92
startListening()93 void SocketExternalCommunicator::startListening()
94 {
95 if ( memory_->create(sizeof(qint32))) {
96 #ifdef Q_OS_UNIX
97 // Handle any further termination signals to ensure the
98 // QSharedMemory block is deleted even if the process crashes
99 setCrashHandler(memory_);
100 #endif
101
102 *reinterpret_cast<qint32*>(memory_->data()) = version();
103 QLocalServer::removeServer(GLOG_SERVICE_NAME);
104
105 connect(server_, SIGNAL(newConnection()), SLOT(onConnection()));
106 server_->listen(GLOG_SERVICE_NAME);
107 }
108 }
109
version() const110 qint32 SocketExternalCommunicator::version() const
111 {
112 return 3;
113 }
114
otherInstance() const115 ExternalInstance* SocketExternalCommunicator::otherInstance() const
116 {
117 try {
118 return static_cast<ExternalInstance*>( new SocketExternalInstance() );
119 }
120 catch ( CantCreateExternalErr ) {
121 LOG(logINFO) << "Cannot find external correspondant, we are the only glogg out there.";
122 return nullptr;
123 }
124 }
125
onConnection()126 void SocketExternalCommunicator::onConnection()
127 {
128 QLocalSocket *socket = server_->nextPendingConnection();
129 QByteArray data;
130 while(socket->waitForReadyRead(100)) {
131 data.append(socket->readAll());
132 }
133
134 socket->close();
135
136 emit loadFile(QString::fromUtf8(data));
137 }
138
139
140
141