1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "ipc/ipc.h"
31 
32 #ifdef OS_WIN
33 #include <windows.h>
34 #else
35 #include <sys/types.h>
36 #include <signal.h>
37 #include <errno.h>
38 #endif
39 
40 #include <cstdlib>
41 
42 #include "base/logging.h"
43 #include "base/port.h"
44 #include "base/singleton.h"
45 #include "base/thread.h"
46 #include "ipc/ipc_path_manager.h"
47 
48 namespace mozc {
49 
50 namespace {
51 
52 class IPCServerThread : public Thread {
53  public:
IPCServerThread(IPCServer * server)54   explicit IPCServerThread(IPCServer *server)
55       : server_(server) {}
~IPCServerThread()56   virtual ~IPCServerThread() {}
Run()57   virtual void Run() {
58     if (server_ != NULL) {
59       server_->Loop();
60     }
61   }
62 
63  private:
64   IPCServer *server_;
65 
66   DISALLOW_COPY_AND_ASSIGN(IPCServerThread);
67 };
68 
69 }  // namespace
70 
LoopAndReturn()71 void IPCServer::LoopAndReturn() {
72   if (server_thread_.get() == NULL) {
73     server_thread_.reset(new IPCServerThread(this));
74     server_thread_->SetJoinable(true);
75     server_thread_->Start("IPCServer");
76   } else {
77     LOG(WARNING) << "Another thead is already running";
78   }
79 }
80 
Wait()81 void IPCServer::Wait() {
82   if (server_thread_.get() != NULL) {
83     server_thread_->Join();
84     server_thread_.reset();
85   }
86 }
87 
~IPCClientInterface()88 IPCClientInterface::~IPCClientInterface() {
89 }
90 
~IPCClientFactoryInterface()91 IPCClientFactoryInterface::~IPCClientFactoryInterface() {
92 }
93 
~IPCClientFactory()94 IPCClientFactory::~IPCClientFactory() {
95 }
96 
NewClient(const string & name,const string & path_name)97 IPCClientInterface *IPCClientFactory::NewClient(const string &name,
98                                                 const string &path_name) {
99   return new IPCClient(name, path_name);
100 }
101 
NewClient(const string & name)102 IPCClientInterface *IPCClientFactory::NewClient(const string &name) {
103   return new IPCClient(name);
104 }
105 
106 // static
GetIPCClientFactory()107 IPCClientFactory *IPCClientFactory::GetIPCClientFactory() {
108   return Singleton<IPCClientFactory>::get();
109 }
110 
GetServerProtocolVersion() const111 uint32 IPCClient::GetServerProtocolVersion() const {
112   DCHECK(ipc_path_manager_);
113   return ipc_path_manager_->GetServerProtocolVersion();
114 }
115 
GetServerProductVersion() const116 const string &IPCClient::GetServerProductVersion() const {
117   DCHECK(ipc_path_manager_);
118   return ipc_path_manager_->GetServerProductVersion();
119 }
120 
GetServerProcessId() const121 uint32 IPCClient::GetServerProcessId() const {
122   DCHECK(ipc_path_manager_);
123   return ipc_path_manager_->GetServerProcessId();
124 }
125 
126 // static
TerminateServer(const string & name)127 bool IPCClient::TerminateServer(const string &name) {
128   IPCClient client(name);
129 
130   if (!client.Connected()) {
131     LOG(ERROR) << "Server " << name << " is not running";
132     return true;
133   }
134 
135   const uint32 pid = client.GetServerProcessId();
136   if (pid == 0) {
137     LOG(ERROR) << "pid is not a valid value: " << pid;
138     return false;
139   }
140 
141 #ifdef OS_WIN
142   HANDLE handle = ::OpenProcess(PROCESS_TERMINATE,
143                                 false, static_cast<DWORD>(pid));
144   if (NULL == handle) {
145     LOG(ERROR) << "OpenProcess failed: " << ::GetLastError();
146     return false;
147   }
148 
149   if (!::TerminateProcess(handle, 0)) {
150     LOG(ERROR) << "TerminateProcess failed: " << ::GetLastError();
151     ::CloseHandle(handle);
152     return false;
153   }
154 
155   VLOG(1) << "Success to terminate the server: " << name << " " << pid;
156 
157   ::CloseHandle(handle);
158 
159   return true;
160 #else
161   if (-1 == ::kill(static_cast<pid_t>(pid), 9)) {
162     LOG(ERROR) << "kill failed: " << errno;
163     return false;
164   }
165 
166   return true;
167 #endif
168 }
169 }  // namespace mozc
170