xref: /glogg/src/socketexternalcom.cpp (revision fcf40f1761134a69881dfa6f1d28d01064374a37) !
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         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 
58 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 
75 uint32_t SocketExternalInstance::getVersion() const
76 {
77     return *reinterpret_cast<uint32_t*>(memory_->data());
78 }
79 
80 SocketExternalCommunicator::SocketExternalCommunicator()
81     : ExternalCommunicator()
82     , memory_(new QSharedMemory(GLOG_SERVICE_NAME))
83     , server_(new QLocalServer)
84 {}
85 
86 SocketExternalCommunicator::~SocketExternalCommunicator()
87 {
88     delete memory_;
89     server_->close();
90     delete server_;
91 }
92 
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 
110 qint32 SocketExternalCommunicator::version() const
111 {
112     return 3;
113 }
114 
115 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 
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