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