xref: /glogg/src/socketexternalcom.cpp (revision 0374f408d6901d76d0f8276791479179a8fc215d)
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 
19 void terminate(int signum)
20 {
21     if (g_staticSharedMemory) {
22         delete g_staticSharedMemory;
23     }
24     ::exit(128 + signum);
25 }
26 
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 
43 SocketExternalInstance::SocketExternalInstance()
44     : ExternalInstance(), memory_(new QSharedMemory(GLOG_SERVICE_NAME) )
45 {
46     if ( !memory_->attach( QSharedMemory::ReadOnly ) ) {
47         throw CantCreateExternalErr();
48     }
49 
50 #ifdef Q_OS_UNIX
51         // Handle any further termination signals to ensure the
52         // QSharedMemory block is deleted even if the process crashes
53         setCrashHandler(memory_);
54 #endif
55 }
56 
57 void SocketExternalInstance::loadFile(const QString &file_name) const
58 {
59     QLocalSocket socket;
60     socket.connectToServer(GLOG_SERVICE_NAME);
61     if (!socket.waitForConnected(1000)) {
62         LOG( logERROR ) << "Failed to connect to socket";
63         return;
64     }
65 
66     socket.write(file_name.toUtf8());
67     if (!socket.waitForBytesWritten(1000)) {
68         LOG( logERROR ) << "Failed to send filename";
69     }
70 
71     socket.close();
72 }
73 
74 uint32_t SocketExternalInstance::getVersion() const
75 {
76     return *reinterpret_cast<uint32_t*>(memory_->data());
77 }
78 
79 SocketExternalCommunicator::SocketExternalCommunicator()
80     : ExternalCommunicator()
81     , memory_(new QSharedMemory(GLOG_SERVICE_NAME))
82     , server_(new QLocalServer)
83 {}
84 
85 SocketExternalCommunicator::~SocketExternalCommunicator()
86 {
87     delete memory_;
88     server_->close();
89     delete server_;
90 }
91 
92 void SocketExternalCommunicator::startListening()
93 {
94     if ( memory_->create(sizeof(qint32))) {
95 #ifdef Q_OS_UNIX
96         // Handle any further termination signals to ensure the
97         // QSharedMemory block is deleted even if the process crashes
98         setCrashHandler(memory_);
99 #endif
100 
101         *reinterpret_cast<qint32*>(memory_->data()) = version();
102         QLocalServer::removeServer(GLOG_SERVICE_NAME);
103 
104         connect(server_, SIGNAL(newConnection()), SLOT(onConnection()));
105         server_->listen(GLOG_SERVICE_NAME);
106     }
107 }
108 
109 qint32 SocketExternalCommunicator::version() const
110 {
111     return 3;
112 }
113 
114 ExternalInstance* SocketExternalCommunicator::otherInstance() const
115 {
116     try {
117         return static_cast<ExternalInstance*>( new SocketExternalInstance() );
118     }
119     catch ( CantCreateExternalErr ) {
120         LOG(logINFO) << "Cannot find external correspondant, we are the only glogg out there.";
121         return nullptr;
122     }
123 }
124 
125 void SocketExternalCommunicator::onConnection()
126 {
127      QLocalSocket *socket = server_->nextPendingConnection();
128      QByteArray data;
129      while(socket->waitForReadyRead(100)) {
130          data.append(socket->readAll());
131      }
132 
133      socket->close();
134 
135      emit loadFile(QString::fromUtf8(data));
136 }
137 
138 
139 
140