1 /*
2    Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "ndb_global.h"
26 #include "ProcessInfo.hpp"
27 #include "OwnProcessInfo.hpp"
28 #include <NdbMutex.h>
29 
30 const char * ndb_basename(const char *path);
31 
32 extern const char * my_progname;
33 
34 /* Static storage; constructor called at process startup by C++ runtime. */
35 ProcessInfo singletonInfo;
36 NdbLockable theApiMutex;
37 
38 /* Public API
39  *
40  */
setOwnProcessInfoAngelPid(Uint32 pid)41 void setOwnProcessInfoAngelPid(Uint32 pid)
42 {
43   theApiMutex.lock();
44   singletonInfo.setAngelPid(pid);
45   theApiMutex.unlock();
46 }
47 
setOwnProcessInfoServerAddress(struct in_addr * addr)48 void setOwnProcessInfoServerAddress(struct in_addr * addr)
49 {
50   theApiMutex.lock();
51   singletonInfo.setHostAddress(addr);
52   theApiMutex.unlock();
53 }
54 
setOwnProcessInfoPort(Uint16 port)55 void setOwnProcessInfoPort(Uint16 port)
56 {
57   theApiMutex.lock();
58   singletonInfo.setPort(port);
59   theApiMutex.unlock();
60 }
61 
62 
63 /* Fill in missing parts of ProcessInfo before providing it to QMgr
64    or ClusterMgr
65 */
66 
67 #ifdef WIN32
68 #include "psapi.h"
69 
getNameFromEnvironment()70 void getNameFromEnvironment()
71 {
72   HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
73                               FALSE, singletonInfo.getPid());
74   GetModuleFileNameEx(handle, 0, singletonInfo.process_name,
75                       singletonInfo.ProcessNameLength);
76 }
77 #else
getNameFromEnvironment()78 void getNameFromEnvironment()
79 {
80   const char * path = getenv("_");
81   if(path)
82   {
83     singletonInfo.setProcessName(ndb_basename(path));
84   }
85 }
86 #endif
87 
88 
89 /* Return angel pid, or zero if no angel.
90    On unix, if we are not a daemon, and also not a process group leader,
91    set parent pid as angel pid.
92    On Windows, return MYSQLD_PARENT_PID if set in the environment.
93 */
getParentPidAsAngel()94 static Uint32 getParentPidAsAngel()
95 {
96 #ifdef WIN32
97   const char * monitor_pid = getenv("MYSQLD_PARENT_PID");
98   if(monitor_pid)
99   {
100     return atoi(monitor_pid);
101   }
102 #else
103   pid_t parent_process_id = getppid();
104   if((parent_process_id != 1)  && (getpgrp() != singletonInfo.getPid()))
105   {
106     return parent_process_id;
107   }
108 #endif
109   return 0;
110 }
111 
112 
113 /* Public API for QMgr and ClusterMgr.
114 */
getOwnProcessInfo(Uint16 nodeId)115 ProcessInfo * getOwnProcessInfo(Uint16 nodeId) {
116   Guard locked(theApiMutex);
117   if(singletonInfo.process_id == 0)
118   {
119     /* Finalize */
120     singletonInfo.setPid();
121     singletonInfo.node_id = nodeId;
122     if(singletonInfo.angel_process_id == 0)
123       singletonInfo.angel_process_id = getParentPidAsAngel();
124     if(singletonInfo.process_name[0] == 0)
125     {
126       if(my_progname)
127         singletonInfo.setProcessName(ndb_basename(my_progname));
128       else
129         getNameFromEnvironment();
130     }
131   }
132 
133   return & singletonInfo;
134 }
135