/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- dmtcp_real_to_virtual_pid
- dmtcp_virtual_to_real_pid
- dmtcp_get_real_pid
- dmtcp_get_real_tid
- dmtcp_real_tgkill
- pidVirt_AtForkParent
- pidVirt_ResetOnFork
- pidVirt_PrepareForExec
- pidVirt_PostExec
- openSharedFile
- openOriginalToCurrentMappingFiles
- pidVirt_PostRestart
- pidVirt_PostRestartRefill
- pidVirt_ThreadExit
- dmtcp_event_hook
1 /****************************************************************************
2 * Copyright (C) 2006-2013 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src). *
6 * *
7 * DMTCP:dmtcp/src is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 #include <sys/types.h>
23 #include "jalloc.h"
24 #include "jassert.h"
25 #include "jconvert.h"
26 #include "jfilesystem.h"
27 #include "pidwrappers.h"
28 #include "virtualpidtable.h"
29 #include "dmtcp.h"
30 #include "protectedfds.h"
31
32 using namespace dmtcp;
33
34 extern "C" pid_t dmtcp_update_ppid();
35
36 static string pidMapFile;
37
38 extern "C"
39 pid_t dmtcp_real_to_virtual_pid(pid_t realPid)
40 {
41 return REAL_TO_VIRTUAL_PID(realPid);
42 }
43
44 extern "C"
45 pid_t dmtcp_virtual_to_real_pid(pid_t virtualPid)
46 {
47 return VIRTUAL_TO_REAL_PID(virtualPid);
48 }
49
50 extern "C"
51 pid_t dmtcp_get_real_pid()
52 {
53 return _real_getpid();
54 }
55
56 extern "C"
57 pid_t dmtcp_get_real_tid()
58 {
59 return _real_gettid();
60 }
61
62 extern "C"
63 int dmtcp_real_tgkill(pid_t tgid, pid_t tid, int sig)
64 {
65 return _real_tgkill(tgid, tid, sig);
66 }
67
68 static void pidVirt_AtForkParent(DmtcpEventData_t *data)
69 {
70 pid_t virtPpid = getppid();
71 pid_t realPpid = VIRTUAL_TO_REAL_PID(virtPpid);
72 Util::setVirtualPidEnvVar(getpid(), virtPpid, realPpid);
73 }
74
75 static void pidVirt_ResetOnFork(DmtcpEventData_t *data)
76 {
77 VirtualPidTable::instance().resetOnFork();
78 }
79
80 static void pidVirt_PrepareForExec(DmtcpEventData_t *data)
81 {
82 pid_t virtPpid = getppid();
83 pid_t realPpid = VIRTUAL_TO_REAL_PID(virtPpid);
84 Util::setVirtualPidEnvVar(getpid(), virtPpid, realPpid);
85
86 JASSERT(data != NULL);
87 jalib::JBinarySerializeWriterRaw wr ("", data->serializerInfo.fd);
88 VirtualPidTable::instance().serialize(wr);
89 }
90
91 static void pidVirt_PostExec(DmtcpEventData_t *data)
92 {
93 JASSERT(data != NULL);
94 jalib::JBinarySerializeReaderRaw rd ("", data->serializerInfo.fd);
95 VirtualPidTable::instance().serialize(rd);
96 VirtualPidTable::instance().refresh();
97 }
98
99 static int openSharedFile(string name, int flags)
100 {
101 int fd;
102 int errno_bkp;
103 // try to create, truncate & open file
104
105 jalib::string dir = jalib::Filesystem::DirName(name);
106 JTRACE("shared file dir:")(dir);
107 jalib::Filesystem::mkdir_r(dir, 0755);
108
109 if ((fd = _real_open(name.c_str(), O_EXCL|O_CREAT|O_TRUNC | flags, 0600)) >= 0) {
110 return fd;
111 }
112 errno_bkp = errno;
113
114 JTRACE("_real_open: ")(strerror(errno))(fd)(flags);
115
116 if ( (fd < 0) && (errno_bkp == EEXIST) ) {
117 errno = 0;
118 if ((fd = _real_open(name.c_str(), flags, 0600)) >= 0) {
119 return fd;
120 }
121 }
122 // unable to create & open OR open
123 JASSERT(false)(name)(strerror(errno)).Text("Cannot open file");
124 return -1;
125 }
126
127 static void openOriginalToCurrentMappingFiles()
128 {
129 int fd;
130 ostringstream o;
131 o << dmtcp_get_tmpdir() << "/dmtcpPidMap."
132 << dmtcp_get_computation_id_str() << "."
133 << std::hex << dmtcp_get_coordinator_timestamp();
134 pidMapFile = o.str();
135 // Open and create pidMapFile if it doesn't exist.
136 JTRACE("Open dmtcpPidMapFile")(pidMapFile);
137 if (!Util::isValidFd(PROTECTED_PIDMAP_FD)) {
138 fd = openSharedFile(pidMapFile, O_RDWR);
139 JASSERT (fd != -1);
140 JASSERT (dup2 (fd, PROTECTED_PIDMAP_FD) == PROTECTED_PIDMAP_FD)
141 (pidMapFile);
142 close (fd);
143 }
144 }
145
146 static void pidVirt_PostRestart(DmtcpEventData_t *data)
147 {
148 if ( jalib::Filesystem::GetProgramName() == "screen" )
149 send_sigwinch = 1;
150 // With hardstatus (bottom status line), screen process has diff. size window
151 // Must send SIGWINCH to adjust it.
152 // src/terminal.cpp:restore_term_settings() will send SIGWINCH to process
153 // on restart. This will force 'screen' to execute ioctl wrapper.
154 // The wrapper will report a changed winsize,
155 // so that 'screen' must re-initialize the screen (scrolling regions, etc.).
156 // The wrapper will also send a second SIGWINCH. Then 'screen' will
157 // call ioctl and get the correct window size and resize again.
158 // We can't just send two SIGWINCH's now, since window size has not
159 // changed yet, and 'screen' will assume that there's nothing to do.
160
161 dmtcp_update_ppid();
162 openOriginalToCurrentMappingFiles();
163 VirtualPidTable::instance().writeMapsToFile(PROTECTED_PIDMAP_FD);
164 }
165
166 static void pidVirt_PostRestartRefill(DmtcpEventData_t *data)
167 {
168 VirtualPidTable::instance().readMapsFromFile(PROTECTED_PIDMAP_FD);
169 dmtcp_close_protected_fd(PROTECTED_PIDMAP_FD);
170 unlink(pidMapFile.c_str());
171 }
172
173 static void pidVirt_ThreadExit(DmtcpEventData_t *data)
174 {
175 /* This thread has finished its execution, do some cleanup on our part.
176 * erasing the original_tid entry from virtualpidtable
177 * FIXME: What if the process gets checkpointed after erase() but before the
178 * thread actually exits?
179 */
180 pid_t tid = dmtcp_gettid();
181 VirtualPidTable::instance().erase(tid);
182 }
183
184 extern "C" void dmtcp_event_hook(DmtcpEvent_t event, DmtcpEventData_t *data)
185 {
186 switch (event) {
187 case DMTCP_EVENT_ATFORK_PARENT:
188 pidVirt_AtForkParent(data);
189 break;
190
191 case DMTCP_EVENT_ATFORK_CHILD:
192 pidVirt_ResetOnFork(data);
193 break;
194
195 case DMTCP_EVENT_PRE_EXEC:
196 pidVirt_PrepareForExec(data);
197 break;
198
199 case DMTCP_EVENT_POST_EXEC:
200 pidVirt_PostExec(data);
201 break;
202
203 case DMTCP_EVENT_RESTART:
204 pidVirt_PostRestart(data);
205 break;
206
207 case DMTCP_EVENT_REFILL:
208 if (data->refillInfo.isRestart) {
209 pidVirt_PostRestartRefill(data);
210 }
211 break;
212
213 case DMTCP_EVENT_PTHREAD_RETURN:
214 case DMTCP_EVENT_PTHREAD_EXIT:
215 pidVirt_ThreadExit(data);
216 break;
217
218 default:
219 break;
220 }
221
222 DMTCP_NEXT_EVENT_HOOK(event, data);
223 return;
224 }