1 /*****************************************************************************
2 * Copyright (C) 2006-2009 by Michael Rieker, Jason Ansel, Kapil Arya, and *
3 * Gene Cooperman *
4 * mrieker@nii.net, jansel@csail.mit.edu, kapil@ccs.neu.edu, and *
5 * gene@ccs.neu.edu *
6 * *
7 * This file is part of the MTCP module of DMTCP (DMTCP:mtcp). *
8 * *
9 * DMTCP:mtcp is free software: you can redistribute it and/or *
10 * modify it under the terms of the GNU Lesser General Public License as *
11 * published by the Free Software Foundation, either version 3 of the *
12 * License, or (at your option) any later version. *
13 * *
14 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU Lesser General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU Lesser General Public *
20 * License along with DMTCP:dmtcp/src. If not, see *
21 * <http://www.gnu.org/licenses/>. *
22 *****************************************************************************/
23
24 #include "mtcp_ptrace.h"
25 #include <pthread.h>
26 #include <semaphore.h>
27 #include <unistd.h>
28
29 #ifdef PTRACE
30
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <sched.h>
38 #include <sys/user.h>
39 #include <sys/syscall.h>
40
41 #define GETTID() (int)syscall(SYS_gettid)
42
43 int only_once = 0;
44
45 const unsigned char DMTCP_SYS_sigreturn = 0x77;
46 const unsigned char DMTCP_SYS_rt_sigreturn = 0xad;
47
48 static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
49
50 static __thread int is_waitpid_local = 0;
51 static __thread int is_ptrace_local = 0;
52 static __thread pid_t saved_pid = -1;
53 static __thread int saved_status = -1;
54 static __thread int has_status_and_pid = 0;
55
56 __thread pid_t setoptions_superior = -1;
57 __thread int is_ptrace_setoptions = FALSE;
58
59 static pthread_mutex_t ptrace_pairs_mutex = PTHREAD_MUTEX_INITIALIZER;
60
61 struct ckpt_thread {
62 pid_t pid;
63 pid_t tid;
64 };
65
66 sem_t ptrace_read_pairs_sem;
67 int init_ptrace_read_pairs_sem = 0;
68
69 sem_t __sem;
70 int init__sem = 0;
71
72 char ptrace_shared_file[MAXPATHLEN];
73 char ptrace_setoptions_file[MAXPATHLEN];
74 char checkpoint_threads_file[MAXPATHLEN];
75
76 int has_ptrace_file = 0;
77 pid_t delete_ptrace_leader = -1;
78 int has_setoptions_file = 0;
79 pid_t delete_setoptions_leader = -1;
80 int has_checkpoint_file = 0;
81 pid_t delete_checkpoint_leader = -1;
82
83 struct ptrace_tid_pairs ptrace_pairs[MAX_PTRACE_PAIRS_COUNT];
84 int ptrace_pairs_count = 0;
85 int init_ptrace_pairs = 0;
86
87 /***************************************************************************/
88 /* THIS CODE MUST BE CHANGED TO CHECK TO SEE IF THE USER CREATES EVEN MORE */
89 /* THREADS. */
90 /***************************************************************************/
91 #define MAX_CKPT_THREADS 100
92 static struct ckpt_thread ckpt_threads[MAX_CKPT_THREADS];
93 static int ckpt_threads_count = 0;
94
95 static void have_file(pid_t pid);
96
97 static int is_checkpoint_thread (pid_t tid);
98
99 static int ptrace_detach_ckpthread(pid_t tgid, pid_t tid, pid_t supid);
100
101 static void sort_ptrace_pairs ();
102
103 static void print_ptrace_pairs ();
104
105 static void reset_ptrace_pairs_entry ( int i );
106
107 void check_size_for_ptrace_file (const char *file) {
108 struct stat buf;
109 if (!stat (file, &buf)) {
110 mtcp_printf ("WARNING: %s has %d bytes.\n", file, buf.st_size);
111 } else {
112 if (errno != ENOENT) {
113 mtcp_printf ("WARNING: stat failed for %s with an error different than ENOENT.\n",
114 ptrace_shared_file);
115 }
116 }
117 }
118
119
120 void init_thread_local()
121 {
122 is_waitpid_local = 0; // no crash on pre-access
123 is_ptrace_local = 0; // no crash on pre-access
124 saved_pid = -1; // no crash on pre-access
125 saved_status = -1; // no crash on pre-access
126 has_status_and_pid = 0; // crash
127
128 setoptions_superior = -1;
129 is_ptrace_setoptions = FALSE;
130 }
131
132
133 /* FIXME: BAD FUNCTION NAME: readall(..., ..., count) would guarantee
134 * to read 'count' characters. This reads zero or more characters
135 * but does EAGAIN/EINTR processing so that the caller doesn't need to do it.
136 * Maybe a name like: read_no_error() ?
137 */
138 ssize_t readall(int fd, void *buf, size_t count)
139 {
140 int rc;
141 do
142 rc = read(fd, buf, count);
143 while (rc == -1 && (errno == EAGAIN || errno == EINTR));
144 if (rc == -1) { /* if not harmless error */
145 mtcp_printf("readall: Internal error\n");
146 mtcp_abort();
147 }
148 return rc; /* else rc >= 0; success */
149 }
150
151 void delete_file (int file, int delete_leader, int has_file)
152 {
153 if ((delete_leader == GETTID()) && has_file) {
154 switch (file) {
155 case 0: {
156 if (unlink(ptrace_shared_file) == -1 && errno != ENOENT) {
157 mtcp_printf("delete_file: unlink failed: %s\n",
158 strerror(errno));
159 mtcp_abort();
160 }
161 break;
162 }
163 case 1: {
164 if (unlink(ptrace_setoptions_file) == -1 && errno != ENOENT) {
165 mtcp_printf("delete_file: unlink failed: %s\n",
166 strerror(errno));
167 mtcp_abort();
168 }
169 break;
170 }
171 case 2: {
172 if (unlink(checkpoint_threads_file) == -1 && errno != ENOENT) {
173 mtcp_printf("delete_file: unlink failed: %s\n",
174 strerror(errno));
175 mtcp_abort();
176 }
177 break;
178 }
179 default: {
180 mtcp_printf ("delete_file: unknown option\n");
181 }
182 }
183 }
184 }
185
186 void ptrace_remove_notexisted()
187 {
188 int i;
189 struct ptrace_tid_pairs temp;
190
191 DPRINTF(("<<<<<<<<<<< start ptrace_remove_notexisted %d\n", GETTID()));
192
193 for (i = 0; i < ptrace_pairs_count; i++) {
194 int tid = ptrace_pairs[i].inferior;
195 char pstate = procfs_state(tid);
196 DPRINTF(("checking status of %d = %c\n",tid,pstate));
197 if( pstate == 0) {
198 // process not exist
199 if ( i != (ptrace_pairs_count - 1)) {
200 temp = ptrace_pairs[i];
201 ptrace_pairs[i] = ptrace_pairs[ptrace_pairs_count - 1];
202 ptrace_pairs[ptrace_pairs_count - 1] = temp;
203 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
204 i--;
205 ptrace_pairs_count--;
206 }
207 else {
208 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
209 ptrace_pairs_count --;
210 break;
211 }
212 }
213 }
214
215 print_ptrace_pairs ();
216 DPRINTF((">>>>>>>>>>> done ptrace_remove_notexisted %d\n", GETTID()));
217 }
218
219 void ptrace_attach_threads(int isRestart)
220 {
221 pid_t superior;
222 pid_t inferior;
223 int last_command;
224 int singlestep_waited_on;
225 struct user_regs_struct regs;
226 long peekdata;
227 long low, upp;
228 int status;
229 unsigned long addr;
230 unsigned long int eflags;
231 int i;
232
233 DPRINTF(("attach started %d\n", GETTID()));
234
235 /*
236 for (i = 0; i < ptrace_pairs_count; i++) {
237 mtcp_printf("tid = %d superior = %d inferior = %d last_command = %d\n", GETTID(), ptrace_pairs[i].superior, ptrace_pairs[i].inferior, ptrace_pairs[i].last_command);
238 }
239 */
240 for (i = 0; i < ptrace_pairs_count; i++) {
241
242 superior = ptrace_pairs[i].superior;
243 inferior = ptrace_pairs[i].inferior;
244 last_command = ptrace_pairs[i].last_command;
245 singlestep_waited_on = ptrace_pairs[i].singlestep_waited_on;
246
247 char inferior_st = ptrace_pairs[i].inferior_st;
248
249 // kill(inferior,0);
250 if (superior == GETTID()) {
251
252 DPRINTF (("(attach) tid = %d superior = %d inferior = %d\n",
253 GETTID(), (int)superior, (int)inferior));
254 // we must make sure the inferior process was created
255
256 sem_wait( &__sem);
257 if (only_once == 0) {
258 have_file (superior);
259 only_once = 1;
260 }
261 sem_post( &__sem);
262 if( is_checkpoint_thread(inferior)) {
263 have_file (inferior);
264 DPRINTF(("ptrace_attach_threads: attach to checkpoint thread: %d\n",inferior));
265 //sleep(5);
266 is_ptrace_local = 1;
267 if (ptrace(PTRACE_ATTACH, inferior, 0, 0) == -1) {
268 DPRINTF(("PTRACE_ATTACH failed for parent = %d child = %d\n", (int)superior, (int)inferior));
269 perror("ptrace_attach_threads: PTRACE_ATTACH for CKPT failed");
270 while(1);
271 mtcp_abort();
272 }
273 is_waitpid_local = 1;
274 if (waitpid(inferior, &status, __WCLONE) == -1) {
275 perror("ptrace_attach_threads: waitpid for ckpt failed\n");
276 mtcp_abort();
277 }
278 if (WIFEXITED(status)) {
279 DPRINTF(("The reason for ckpt child death was %d\n",WEXITSTATUS(status)));
280 }else if(WIFSIGNALED(status)) {
281 DPRINTF(("The reason for ckpt child death was signal %d\n",WTERMSIG(status)));
282 }
283
284 DPRINTF(("ptrace_attach_threads: preCheckpoint state = %c\n",inferior_st));
285 if( inferior_st != 'T' ){
286 is_ptrace_local = 1;
287 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
288 perror("ptrace_attach_threads: PTRACE_CONT failed");
289 mtcp_abort();
290 }
291 } continue;
292 }
293
294
295 is_ptrace_local = 1;
296 if (ptrace(PTRACE_ATTACH, inferior, 0, 0) == -1) {
297 mtcp_printf("PTRACE_ATTACH failed for parent = %d child = %d\n", (int)superior, (int)inferior);
298 perror("ptrace_attach_threads: PTRACE_ATTACH failed");
299 mtcp_abort();
300 }
301 create_file (inferior);
302 while(1) {
303 // mtcp_printf("new iter for sup=%d, inf=%d\n",superior,inferior);
304 is_waitpid_local = 1;
305 if( waitpid(inferior, &status, 0 ) == -1) {
306 is_waitpid_local = 1;
307 if( waitpid(inferior, &status, __WCLONE ) == -1) {
308 while(1);
309 perror("ptrace_attach_threads: waitpid failed\n");
310 mtcp_abort();
311 }
312 }
313 if (WIFEXITED(status)) {
314 DPRINTF(("The reason for childs death was %d\n",WEXITSTATUS(status)));
315 }else if(WIFSIGNALED(status)) {
316 DPRINTF(("The reason for child's death was signal %d\n",WTERMSIG(status)));
317 }
318
319 if (ptrace(PTRACE_GETREGS, inferior, 0, ®s) < 0) {
320 perror("ptrace_attach_threads: PTRACE_GETREGS failed");
321 mtcp_abort();
322 }
323 #ifdef __x86_64__
324 peekdata = ptrace(PTRACE_PEEKDATA, inferior, regs.rip, 0);
325 #else
326 peekdata = ptrace(PTRACE_PEEKDATA, inferior, regs.eip, 0);
327 #endif
328 low = peekdata & 0xff;
329 peekdata >>=8;
330 upp = peekdata & 0xff;
331
332 #ifdef __x86_64__
333 if ((low == 0xf) && (upp == 0x05) && (regs.rax == 0xf)) {
334 /* This code is yet to be written */
335 if ( isRestart ) {
336 if (last_command == PTRACE_SINGLESTEP_COMMAND ) {
337 if (regs.eax == DMTCP_SYS_sigreturn) {
338 addr = regs.esp;
339 }
340 else {
341 DPRINTF(("SYS_RT_SIGRETURN\n"));
342 //UNTESTED -> TODO; gdb very unclear
343 addr = regs.esp + 8;
344 addr = ptrace(PTRACE_PEEKDATA, inferior, addr, 0);
345 addr += 20;
346 }
347 addr += EFLAGS_OFFSET;
348 errno = 0;
349 if ((eflags = ptrace(PTRACE_PEEKDATA, inferior, (void *)addr, 0)) < 0) {
350 if (errno != 0) {
351 perror ("ptrace_attach_threads: PTRACE_PEEKDATA failed");
352 mtcp_abort ();
353 }
354 }
355 eflags |= 0x0100;
356 printf("inferior = %d addr = %ld eflags = %ld \n", inferior, addr, eflags);
357 if (ptrace(PTRACE_POKEDATA, inferior, addr, eflags) < 0) {
358 perror("ptrace_attach_threads: PTRACE_POKEDATA failed");
359 mtcp_abort();
360 }
361 }
362 else if (inferior_st != 'T' ) {
363 /*
364 TODO: remove in future as GROUP restore becames stable
365 - Artem
366 if (getsid(inferior) == getsid(superior)) {
367 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
368 {
369 perror("ptrace_attach_threads: tcsetpgrp failed");
370 mtcp_abort();
371 }
372 }
373 */
374 is_ptrace_local = 1;
375 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
376 perror("ptrace_attach_threads: PTRACE_CONT failed");
377 mtcp_abort();
378 }
379 }
380 } else {
381 if (inferior_st != 'T')
382 {
|
Event implicit_func_decl: |
function "getsid" declared implicitly |
|
Event caretline: |
^ |
383 if (getsid(inferior) == getsid(superior)) {
384 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
385 {
386 perror("ptrace_attach_threads: tcsetpgrp failed");
387 mtcp_abort();
388 }
389 }
390 is_ptrace_local = 1;
391 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
392 perror("ptrace_attach_threads: PTRACE_CONT failed");
393 mtcp_abort();
394 }
395 }
396 }
397
398 if (inferior_st == 'T') {
399 /* this is needed because we are hitting the same breakpoint
400 twice if we were ckpt at a breakpoint
401 info breakpoint was giving incorrect values
402 */
403 is_ptrace_local = 1;
404 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
405 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
406 mtcp_abort();
407 }
408 is_waitpid_local = 1;
409 if( waitpid(inferior, &status, 0 ) == -1) {
410 is_waitpid_local = 1;
411 if( waitpid(inferior, &status, __WCLONE ) == -1) {
412 while(1);
413 perror("ptrace_attach_threads: waitpid failed\n");
414 mtcp_abort();
415 }
416 }
417 }
418 break;
419 }
420 #else
421 if (((low == 0xcd) && (upp == 0x80)) &&
422 ((regs.eax == DMTCP_SYS_sigreturn) ||
423 (regs.eax == DMTCP_SYS_rt_sigreturn))) {
424 if ( isRestart ) {
425 if (last_command == PTRACE_SINGLESTEP_COMMAND ) {
426 if (regs.eax == DMTCP_SYS_sigreturn) {
427 addr = regs.esp;
428 }
429 else {
430 DPRINTF(("SYS_RT_SIGRETURN\n"));
431 //UNTESTED -> TODO; gdb very unclear
432 addr = regs.esp + 8;
433 addr = ptrace(PTRACE_PEEKDATA, inferior, addr, 0);
434 addr += 20;
435 }
436 addr += EFLAGS_OFFSET;
437 errno = 0;
438 if ((eflags = ptrace(PTRACE_PEEKDATA, inferior, (void *)addr, 0)) < 0) {
439 if (errno != 0) {
440 perror ("ptrace_attach_threads: PTRACE_PEEKDATA failed");
441 mtcp_abort ();
442 }
443 }
444 eflags |= 0x0100;
445 if (ptrace(PTRACE_POKEDATA, inferior, (void *)addr, eflags) < 0) {
446 perror("ptrace_attach_threads: PTRACE_POKEDATA failed");
447 mtcp_abort();
448 }
449 } else if (inferior_st != 'T') {
450 if (getsid(inferior) == getsid(superior)) {
451 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
452 {
453 perror("ptrace_attach_threads: tcsetpgrp failed");
454 mtcp_abort();
455 }
456 }
457 is_ptrace_local = 1;
458 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
459 perror("ptrace_attach_threads: PTRACE_CONT failed");
460 mtcp_abort();
461 }
462 }
463 } else {
464 if (inferior_st != 'T') {
465 if (getsid(inferior) == getsid(superior)) {
466 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
467 {
468 perror("ptrace_attach_threads: tcsetpgrp failed");
469 mtcp_abort();
470 }
471 }
472 is_ptrace_local = 1;
473 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
474 perror("ptrace_attach_threads: PTRACE_CONT failed");
475 mtcp_abort();
476 }
477 }
478 }
479
480
481 if (inferior_st == 'T') {
482 /* this is needed because we are hitting the same breakpoint
483 twice if we were ckpt at a breakpoint
484 info breakpoint was giving incorrect values
485 */
486 is_ptrace_local = 1;
487 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
488 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
489 mtcp_abort();
490 }
491 is_waitpid_local = 1;
492 if( waitpid(inferior, &status, 0 ) == -1) {
493 is_waitpid_local = 1;
494 if( waitpid(inferior, &status, __WCLONE ) == -1) {
495 while(1);
496 perror("ptrace_attach_threads: waitpid failed\n");
497 mtcp_abort();
498 }
499 }
500 }
501 break;
502 }
503 #endif
504 is_ptrace_local = 1;
505 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
506 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
507 mtcp_abort();
508 }
509 }
510 }
511 else if (inferior == GETTID()) {
512
513 create_file (superior);
514 have_file (inferior);
515 }
516 }
517 DPRINTF(("ptrace_attach_threads: finished for %d\n", GETTID()));
518 }
519
520 void ptrace_detach_checkpoint_threads ()
521 {
522 int i,ret;
523 pid_t tgid;
524
525 // Release only checkpoint threads
526 for (i = 0; i < ptrace_pairs_count; i++) {
527 int tid = ptrace_pairs[i].inferior;
528 int sup = ptrace_pairs[i].superior;
529 tgid = is_checkpoint_thread (tid);
530 if ((sup == GETTID()) && tgid ) {
531 DPRINTF(("ptrace_detach_checkpoint_threads: ptrace_detach_ckpthread(%d,%d,%d)\n",
532 tgid,tid,sup));
533 if( ret = ptrace_detach_ckpthread(tgid,tid,sup) ){
534 if( ret == -ENOENT ){
535 DPRINTF(("%s: process not exist %d\n",__FUNCTION__,tid));
536 }
537 mtcp_abort();
538 }
539 }
540 }
541 DPRINTF((">>>>>>>>> done ptrace_detach_checkpoint_threads %d\n", GETTID()));
542 }
543
544 void ptrace_detach_user_threads ()
545 {
546 int i;
547 int status = 0;
548
549 for(i = 0; i < ptrace_pairs_count; i++) {
550 /*
551 mtcp_printf("tid = %d superior = %d inferior = %d last_command = %d\n", GETTID(), ptrace_pairs[i].superior,
552 ptrace_pairs[i].inferior, ptrace_pairs[i].last_command);
553 */
554 if( is_checkpoint_thread(ptrace_pairs[i].inferior) ){
555 DPRINTF(("ptrace_detach_user_threads: SKIP checkpoint thread %d\n",ptrace_pairs[i].inferior));
556 continue;
557 }
558
559 if( ptrace_pairs[i].superior == GETTID()) {
560 char pstate;
561 // required for all user threads to get SIGUSR2 from their checkpoint thread
562 // TODO: to be removed by waiting for the signal to have been delivered
563 // sleep(PTRACE_SLEEP_INTERVAL);
564 int tid = ptrace_pairs[i].inferior, tpid;
565 DPRINTF(("start waiting on %d\n",tid));
566
567 // Check if status of this thread already read by debugger
568 pstate = procfs_state(tid);
569 DPRINTF(("procfs_state(%d) = %c\n",tid,pstate));
570 if( pstate == 0){
571 // process not exist
572 mtcp_printf("%s: process not exist %d\n",__FUNCTION__,tid);
573 mtcp_abort();
574 } else if( pstate == 'T'){
575 // There can be posibility that GDB (or other) reads status of this
576 // thread before us. So we will block. We don't want that.
577 // Read anyway but without hang
578 DPRINTF(("!!!! Process already stopped !!!!\n"));
579
580 is_waitpid_local = 1;
581 tpid = waitpid (tid, &status, WNOHANG);
582 if(tpid == -1 && errno == ECHILD){
583 DPRINTF(("Check cloned process\n"));
584 // Try again with __WCLONE to check cloned processes.
585 is_waitpid_local = 1;
586 if( (tpid = waitpid (tid, &status, __WCLONE | WNOHANG ) ) == -1 ){
587 DPRINTF(("ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): : %s\n",
588 strerror(errno)));
589 }
590 }
591
592 DPRINTF(("tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
593 tid,tpid,WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,WSTOPSIG(status)));
594 }else{
595 // Process not in stopped state. We are in signal handler of GDB thread which waits for status change
596 // for this process. Now it is safe to call blocking waitpid.
597
598 DPRINTF(("!!!! Process is not stopped yet !!!!\n"));
599 is_waitpid_local = 1;
600 tpid = waitpid (tid, &status, 0);
601 if(tpid == -1 && errno == ECHILD){
602 DPRINTF(("Check cloned process\n"));
603 // Try again with __WCLONE to check cloned processes.
604 is_waitpid_local = 1;
605 if( (tpid = waitpid (tid, &status, __WCLONE ) ) == -1 ){
606 mtcp_printf("ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
607 strerror(errno));
608 }
609 }
610 DPRINTF(("tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
611 tid,tpid,WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,WSTOPSIG(status)));
612 if(WIFSTOPPED(status)) {
613 if (WSTOPSIG(status) == MTCP_DEFAULT_SIGNAL)
614 DPRINTF(("user thread %d was stopped by the delivery of MTCP_DEFAULT_SIGNAL\n",tid)); else{ //we should never get here
615 DPRINTF(("user thread %d was stopped by the delivery of %d\n", tid, WSTOPSIG(status))
616 );
617 }
618 }else //we should never end up here
619 DPRINTF(("user thread %d was NOT stopped by a signal\n", ptrace_pairs[i].inferior));
620 }
621
622 if (( ptrace_pairs[i].last_command == PTRACE_SINGLESTEP_COMMAND ) &&
623 ( ptrace_pairs[i].singlestep_waited_on == FALSE )) {
624 //is_waitpid_local = 1;
625 has_status_and_pid = 1;
626 saved_status = status;
627 DPRINTF(("+++++++++++++++++++++++++ptrace_detach_user_threads: AFTER WAITPID %d\n",
628 status));
629 ptrace_pairs[i].singlestep_waited_on = TRUE;
630 ptrace_pairs[i].last_command = PTRACE_UNSPECIFIED_COMMAND;
631 }
632
633 DPRINTF(("tid = %d detaching superior = %d from inferior = %d\n",
634 GETTID(), (int)ptrace_pairs[i].superior, (int)ptrace_pairs[i].inferior));
635 have_file (ptrace_pairs[i].inferior);
636 is_ptrace_local = 1;
637 if (ptrace(PTRACE_DETACH, ptrace_pairs[i].inferior, 0, MTCP_DEFAULT_SIGNAL) == -1) {
638 DPRINTF(("ptrace_detach_user_threads: parent = %d child = %d\n",
639 (int)ptrace_pairs[i].superior,
640 (int)ptrace_pairs[i].inferior));
641 DPRINTF(("ptrace_detach_user_threads: PTRACE_DETACH failed with error=%d",errno));
642 }
643 }
644 }
645 DPRINTF((">>>>>>>>> done ptrace_detach_user_threads %d\n", GETTID()));
646 }
647
648 void ptrace_lock_inferiors()
649 {
650 char file[SYNCHRONIZATIONPATHLEN];
651 snprintf(file,SYNCHRONIZATIONPATHLEN,"%s/dmtcp_ptrace_unlocked.%d",dir,GETTID());
652 unlink(file);
653 }
654
655 void ptrace_unlock_inferiors()
656 {
657 char file[SYNCHRONIZATIONPATHLEN];
658 int fd;
659 snprintf(file, SYNCHRONIZATIONPATHLEN, "%s/dmtcp_ptrace_unlocked.%d",dir,GETTID());
660 fd = creat(file,0644);
661 if( fd < 0 ){
662 mtcp_printf("init_lock: Error while creating lock file: %s\n",
663 strerror(errno));
664 mtcp_abort();
665 }
666 close(fd);
667 }
668
669 void create_file(pid_t pid)
670 {
671 char str[SYNCHRONIZATIONPATHLEN];
672 int fd;
673
674 memset(str, 0, SYNCHRONIZATIONPATHLEN);
675 sprintf(str, "%s/%d", dir, pid);
676
677 fd = open(str, O_CREAT|O_APPEND|O_WRONLY, 0644);
678 if (fd == -1) {
679 mtcp_printf("create_file: Error opening file %s\n: %s\n",
680 str, strerror(errno));
681 mtcp_abort();
682 }
683 if ( close(fd) != 0 ) {
684 mtcp_printf("create_file: Error closing file\n: %s\n",
685 strerror(errno));
686 mtcp_abort();
687 }
688 }
689
690 static void have_file(pid_t pid)
691 {
692 char str[SYNCHRONIZATIONPATHLEN];
693 int fd;
694
695 memset(str, 0, SYNCHRONIZATIONPATHLEN);
696 sprintf(str, "%s/%d", dir, pid);
697 while(1) {
698 fd = open(str, O_RDONLY);
699 if (fd != -1) {
700 if (close(fd) != 0) {
701 mtcp_printf("have_file: Error closing file: %s\n",
702 strerror(errno));
703 mtcp_abort();
704 }
705 if (unlink(str) == -1) {
706 mtcp_printf("have_file: unlink failed: %s\n",
707 strerror(errno));
708 mtcp_abort();
709 }
710 break;
711 }
712 usleep(100);
713 }
714 }
715
716 void ptrace_wait4(pid_t pid)
717 { char file[SYNCHRONIZATIONPATHLEN];
718 struct stat buf;
719 snprintf(file,SYNCHRONIZATIONPATHLEN,"%s/dmtcp_ptrace_unlocked.%d",dir,pid);
720
721 DPRINTF(("%d: Start waiting for superior\n",GETTID()));
722 while( stat(file,&buf) < 0 ){
723 struct timespec ts;
724 DPRINTF(("%d: Superior is not ready\n",GETTID()));
725 ts.tv_sec = 0;
726 ts.tv_nsec = 100000000;
727 if( errno != ENOENT ){
728 mtcp_printf("prtrace_wait4: Unexpected error in stat: %d\n",errno);
729 mtcp_abort();
730 }
731 nanosleep(&ts,NULL);
732 }
733 DPRINTF(("%d: Superior unlocked us\n",GETTID()));
734 }
735
736 /*************************************************************************/
737 /* Utilities for ptrace code */
738 /* IF ALL THESE FUNCTIONS MUST EXIST INSIDE mtcp.c AND NOT IN SEAPARATE */
739 /* FILE, THEN WE MUST RENAME THEM ALL WITH SOME PREFIX LIKE pt_ */
740 /* (DIFFERENT NAMESPACE FROM REST OF FILE). IF WE CAN MOVE THEM TO */
741 /* A DIFFERENT FILE, THAT WOULD BE EVEN BETTER. - Gene */
742 /*************************************************************************/
743 static void reset_ptrace_pairs_entry ( int i )
744 {
745 ptrace_pairs[i].last_command = PTRACE_UNSPECIFIED_COMMAND;
746 ptrace_pairs[i].singlestep_waited_on = FALSE;
747 ptrace_pairs[i].free = TRUE;
748 ptrace_pairs[i].inferior_st = 'u';
749 }
750
751 static void move_last_ptrace_pairs_entry_to_i ( int i )
752 {
753 ptrace_pairs[i].superior = ptrace_pairs[ptrace_pairs_count-1].superior;
754 ptrace_pairs[i].inferior = ptrace_pairs[ptrace_pairs_count-1].inferior;
755 ptrace_pairs[i].last_command = ptrace_pairs[ptrace_pairs_count-1].last_command;
756 ptrace_pairs[i].singlestep_waited_on = ptrace_pairs[ptrace_pairs_count-1].singlestep_waited_on;
757 ptrace_pairs[i].free = ptrace_pairs[ptrace_pairs_count-1].free;
758 ptrace_pairs[i].inferior_st = ptrace_pairs[ptrace_pairs_count-1].inferior_st;
759 }
760
761 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
762 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
763 * WE'RE A GUEST IN HIS PROCESS. - Gene
764 */
765 void remove_from_ptrace_pairs ( pid_t superior, pid_t inferior )
766 {
767 int i;
768 for (i = 0; i < ptrace_pairs_count; i++) {
769 if ((ptrace_pairs[i].superior == superior) && (ptrace_pairs[i].inferior == inferior)) {
770 break;
771 }
772 }
773 if (i == ptrace_pairs_count) return;
774 if (i != (ptrace_pairs_count-1)) {
775 pthread_mutex_lock(&ptrace_pairs_mutex);
776 move_last_ptrace_pairs_entry_to_i(i);
777 reset_ptrace_pairs_entry(ptrace_pairs_count-1);
778 ptrace_pairs_count--;
779 pthread_mutex_unlock(&ptrace_pairs_mutex);
780 }
781 else {
782 pthread_mutex_lock(&ptrace_pairs_mutex);
783 reset_ptrace_pairs_entry(i);
784 ptrace_pairs_count--;
785 pthread_mutex_unlock(&ptrace_pairs_mutex);
786 }
787 }
788
789 static int is_in_ptrace_pairs ( pid_t superior, pid_t inferior )
790 {
791 int i;
792 for (i = 0; i < ptrace_pairs_count; i++) {
793 if ((ptrace_pairs[i].superior == superior) && (ptrace_pairs[i].inferior == inferior)) return i;
794 }
795 return -1;
796 }
797
798 static void add_to_ptrace_pairs ( pid_t superior, pid_t inferior, int last_command, int singlestep_waited_on )
799 {
800 struct ptrace_tid_pairs new_pair;
801
802 new_pair.superior = superior;
803 new_pair.inferior = inferior;
804 new_pair.last_command = last_command;
805 new_pair.singlestep_waited_on = singlestep_waited_on;
806 new_pair.free = FALSE;
807 new_pair.inferior_st = 'u';
808 new_pair.eligible_for_deletion = TRUE;
809
810 pthread_mutex_lock(&ptrace_pairs_mutex);
811 ptrace_pairs[ptrace_pairs_count] = new_pair;
812 ptrace_pairs_count++;
813 pthread_mutex_unlock(&ptrace_pairs_mutex);
814 }
815
816 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
817 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
818 * WE'RE A GUEST IN HIS PROCESS. - Gene
819 */
820 void handle_command ( pid_t superior, pid_t inferior, int last_command )
821 {
822 int index = is_in_ptrace_pairs ( superior, inferior );
823 if ( index >= 0 ) {
824 ptrace_pairs[index].last_command = last_command;
825 if ( last_command == PTRACE_SINGLESTEP_COMMAND ) ptrace_pairs[index].singlestep_waited_on = FALSE;
826 }
827 else {
828 /* not in the ptrace pairs array; reason: inferior did an PTRACE_TRACEME and now the superior is issuing commands */
829 add_to_ptrace_pairs( superior, inferior, last_command, FALSE );
830 }
831 }
832
833 enum {
834 SORT_BY_SUPERIOR = 0,
835 SORT_BY_INFERIOR
836 };
837
838 static int find_slot (int seed) {
839 int i;
840 pid_t inferior;
841 for (i = seed; i >= 0; i--) {
842 inferior = ptrace_pairs[i].inferior;
843 if (!is_checkpoint_thread(inferior))
844 return i;
845 }
846 return -1;
847 }
848
849 /* This function moves all checkpoint threads at the end of ptrace_pairs array.
850 * It returns the index in ptrace_pairs array where ckpt threads are located. */
851 static int move_ckpt_threads_towards_end () {
852 int i;
853 struct ptrace_tid_pairs temp;
854 pid_t superior;
855 pid_t inferior;
856 int limit = ptrace_pairs_count;
857 int ckpt_threads = 0;
858
859 int slot = find_slot(ptrace_pairs_count - 1);
860 for (i = 0; i < limit; i++) {
861 inferior = ptrace_pairs[i].inferior;
862 if (is_checkpoint_thread(inferior)) {
863 ckpt_threads++;
864 if (slot > i) {
865 temp = ptrace_pairs[i];
866 ptrace_pairs[i] = ptrace_pairs[slot];
867 ptrace_pairs[slot] = temp;
868 limit = slot;
869 slot = find_slot(slot - 1);
870 }
871 }
872 }
873 return ckpt_threads;
874 }
875
876 static pid_t get_pid_by_key (int key, int index) {
877 if (key == SORT_BY_SUPERIOR)
878 return ptrace_pairs[index].superior;
879 else if (key == SORT_BY_INFERIOR)
880 return ptrace_pairs[index].inferior;
881 return -1;
882 }
883
884 static void sort_ptrace_pairs_by_key (int key, int begin, int end) {
885 int i, j;
886 pid_t upper_pid;
887 pid_t inner_pid;
888 pid_t temp_pid;
889 struct ptrace_tid_pairs temp;
890 for (i = begin; i < (end - 1); i++) {
891 upper_pid = get_pid_by_key (key, i);
892 for (j = i + 1; j < end; j++) {
893 inner_pid = get_pid_by_key (key, j);
894 if (upper_pid < inner_pid) {
895 temp = ptrace_pairs[i];
896 ptrace_pairs[i] = ptrace_pairs[j];
897 ptrace_pairs[j] = temp;
898 temp_pid = upper_pid;
899 upper_pid = inner_pid;
900 inner_pid = temp_pid;
901 }
902 }
903 }
904 }
905
906 static void sort_ptrace_pairs_within_limit (int begin, int end) {
907 sort_ptrace_pairs_by_key (SORT_BY_SUPERIOR, begin, end);
908 int ref_superior;
909 int superior;
910 int inferior;
911 int start = begin;
912 int i;
913 ref_superior = ptrace_pairs[0].superior;
914 for (i = (start + 1); i < end; i++) {
915 superior = ptrace_pairs[i].superior;
916 if (superior != ref_superior) {
917 sort_ptrace_pairs_by_key (SORT_BY_INFERIOR, start, i);
918 ref_superior = superior;
919 start = i;
920 }
921 }
922 sort_ptrace_pairs_by_key (SORT_BY_INFERIOR, start, end);
923 }
924
925 static void sort_ptrace_pairs () {
926 if (ptrace_pairs_count <= 1)
927 return;
928 int limit = ptrace_pairs_count - move_ckpt_threads_towards_end ();
929 /* sort all non-checkpoint threads*/
930 sort_ptrace_pairs_within_limit (0, limit);
931 /* sort all checkpoint threads */
932 sort_ptrace_pairs_within_limit (limit, ptrace_pairs_count);
933 }
934
935 static void print_ptrace_pairs ()
936 {
937 int i;
938 DPRINTF(("\n\n"));
939 for ( i = 0; i < ptrace_pairs_count; i++ )
940 DPRINTF(("tid = %d superior = %d inferior = %d \n",
941 GETTID(), (int)ptrace_pairs[i].superior, (int)ptrace_pairs[i].inferior));
942 DPRINTF(("tid = %d ptrace_pairs_count = %d \n", GETTID(), ptrace_pairs_count));
943 DPRINTF(("\n\n"));
944 }
945
946 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
947 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
948 * WE'RE A GUEST IN HIS PROCESS. - Gene
949 */
950
951
952 void write_info_to_file (int file, pid_t superior, pid_t inferior)
953 {
954 int fd;
955 struct flock lock;
956
957 switch (file) {
958 case 0: {
959 fd = open(ptrace_shared_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
960 break;
961 }
962 case 1: {
963 fd = open(ptrace_setoptions_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
964 break;
965 }
966 case 2: {
967 fd = open(checkpoint_threads_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
968 break;
969 }
970 default: {
971 mtcp_printf ("write_info_to_file: unknown option\n");
972 return;
973 }
974 }
975
976 if (fd == -1) {
977 mtcp_printf("write_info_to_file: Error opening file\n: %s\n",
978 strerror(errno));
979 abort();
980 }
981
982 lock.l_type = F_WRLCK;
983 lock.l_whence = SEEK_CUR;
984 lock.l_start = 0;
985 lock.l_len = 0;
986 lock.l_pid = getpid();
987
988 if (fcntl(fd, F_GETLK, &lock ) == -1) {
989 mtcp_printf("write_info_to_file: Error acquiring lock: %s\n",
990 strerror(errno));
991 abort();
992 }
993
994 if (write(fd, &superior, sizeof(pid_t)) == -1) {
995 mtcp_printf("write_info_to_file: Error writing to file: %s\n",
996 strerror(errno));
997 abort();
998 }
999 if (write(fd, &inferior, sizeof(pid_t)) == -1) {
1000 mtcp_printf("write_info_to_file: Error writing to file: %s\n",
1001 strerror(errno));
1002 abort();
1003 }
1004
1005 lock.l_type = F_UNLCK;
1006 lock.l_whence = SEEK_CUR;
1007 lock.l_start = 0;
1008 lock.l_len = 0;
1009
1010 if (fcntl(fd, F_SETLK, &lock) == -1) {
1011 mtcp_printf("write_info_to_file: Error releasing lock: %s\n",
1012 strerror(errno));
1013 abort();
1014 }
1015 if (close(fd) != 0) {
1016 mtcp_printf("write_info_to_file: Error closing file: %s\n",
1017 strerror(errno));
1018 abort();
1019 }
1020 }
1021
1022 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1023 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1024 * WE'RE A GUEST IN HIS PROCESS. - Gene
1025 */
1026 void writeptraceinfo (pid_t superior, pid_t inferior)
1027 {
1028 int index = is_in_ptrace_pairs ( superior, inferior );
1029 if (index == -1 ) {
1030 write_info_to_file (0, superior, inferior);
1031 add_to_ptrace_pairs ( superior, inferior, PTRACE_UNSPECIFIED_COMMAND, FALSE );
1032 }
1033 }
1034
1035 /***********************************************************************
1036 * This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1037 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1038 * WE'RE A GUEST IN THE USER'S PROCESS. - Gene
1039 ***********************************************************************/
1040 void set_singlestep_waited_on ( pid_t superior, pid_t inferior,
1041 int value )
1042 {
1043 int index = is_in_ptrace_pairs ( superior, inferior );
1044 if (( index >= 0 ) && ( ptrace_pairs[index].last_command == PTRACE_SINGLESTEP_COMMAND ))
1045 ptrace_pairs[index].singlestep_waited_on = value;
1046 if (index >= 0)
1047 ptrace_pairs[index].last_command = PTRACE_UNSPECIFIED_COMMAND;
1048 }
1049
1050 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1051 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1052 * WE'RE A GUEST IN HIS PROCESS. - Gene
1053 */
1054 int get_is_waitpid_local ()
1055 {
1056 return is_waitpid_local;
1057 }
1058
1059 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1060 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1061 * WE'RE A GUEST IN HIS PROCESS. - Gene
1062 */
1063 int get_is_ptrace_local ()
1064 {
1065 return is_ptrace_local;
1066 }
1067
1068 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1069 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1070 * WE'RE A GUEST IN HIS PROCESS. - Gene
1071 */
1072 void unset_is_waitpid_local ()
1073 {
1074 is_waitpid_local = 0;
1075 }
1076
1077 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1078 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1079 * WE'RE A GUEST IN HIS PROCESS. - Gene
1080 */
1081 void unset_is_ptrace_local ()
1082 {
1083 is_ptrace_local = 0;
1084 }
1085
1086 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1087 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1088 * WE'RE A GUEST IN HIS PROCESS. - Gene
1089 */
1090 pid_t get_saved_pid ()
1091 {
1092 return saved_pid;
1093 }
1094
1095 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1096 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1097 * WE'RE A GUEST IN HIS PROCESS. - Gene
1098 */
1099 int get_saved_status ()
1100 {
1101 return saved_status;
1102 }
1103
1104 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1105 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1106 * WE'RE A GUEST IN HIS PROCESS. - Gene
1107 */
1108 int get_has_status_and_pid ()
1109 {
1110 return has_status_and_pid;
1111 }
1112
1113 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1114 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1115 * WE'RE A GUEST IN HIS PROCESS. - Gene
1116 */
1117 void reset_pid_status ()
1118 {
1119 saved_pid = -1;
1120 saved_status = -1;
1121 has_status_and_pid = 0;
1122 }
1123
1124 static int is_alive (pid_t pid)
1125 {
1126 char str[20];
1127 int fd;
1128
1129 memset(str, 0, 20);
1130 sprintf(str, "/proc/%d/maps", pid);
1131
1132 fd = open(str, O_RDONLY);
1133 if (fd != -1) {
1134 if ( close(fd) != 0 ) {
1135 mtcp_printf("is_alive: Error closing file: %s\n",
1136 strerror(errno));
1137 mtcp_abort();
1138 }
1139 return 1;
1140 }
1141 return 0;
1142 }
1143
1144 static int is_in_ckpt_threads (pid_t pid)
1145 {
1146 int i;
1147 for (i = 0; i < ckpt_threads_count; i++) {
1148 if (ckpt_threads[i].pid == pid) return 1;
1149 }
1150 return 0;
1151 }
1152 static void print_ckpt_threads ()
1153 {
1154 int i;
1155 for (i = 0; i < ckpt_threads_count; i++)
1156 DPRINTF(("moa = %d pid = %d tid = %d \n",
1157 GETTID(), ckpt_threads[i].pid, ckpt_threads[i].tid));
1158 }
1159
1160 char procfs_state(int tid)
1161 {
1162 char name[64];
1163 char sbuf[256], *S, *tmp;
1164 char state;
1165 int num_read, fd;
1166
1167 sprintf(name,"/proc/%d/stat",tid);
1168 fd = open(name, O_RDONLY, 0);
1169 if( fd < 0 ){
1170 mtcp_printf("procfs_status: cannot open %s\n",name);
1171 return 0;
1172 }
1173 /* THIS CODE CAN'T WORK RELIABLY. SUPPOSE read() RETURNS 0,
1174 * OR -1 WITH EAGAIN OR EINTR? LOOK FOR EXAMPLES IN
1175 * mtcp_restart_nolibc.c:readfile() OR ELSEWHERE. - Gene
1176 */
1177 num_read = read(fd, sbuf, sizeof sbuf - 1);
1178 close(fd);
1179 if(num_read<=0) {
1180 return 0;
1181 }
1182 sbuf[num_read] = '\0';
1183
1184 S = strchr(sbuf, '(') + 1;
1185 tmp = strrchr(S, ')');
1186 S = tmp + 2; // skip ") "
1187
1188 /* YOU SEEM TO WANT S[0] HERE. WHY sscanf? ALSO WHY ARE WE USING
1189 * CAPS ("S") FOR VAR NAME? - Gene
1190 */
1191 sscanf(S, "%c", &state);
1192
1193 return state;
1194 }
1195
1196 void process_ptrace_info (pid_t *delete_ptrace_leader,
1197 int *has_ptrace_file,
1198 pid_t *delete_setoptions_leader, int *has_setoptions_file,
1199 pid_t *delete_checkpoint_leader, int *has_checkpoint_file)
1200 {
1201 int ptrace_fd = -1;
1202 siginfo_t infoop;
1203 int i;
1204 pid_t superior;
1205 pid_t inferior;
1206 int setoptions_fd = -1;
1207 struct ptrace_tid_pairs temp;
1208 int checkpoint_fd = -1;
1209 pid_t pid;
1210 pid_t tid;
1211 struct ckpt_thread ckpt_thread_temp;
1212
1213 DPRINTF((">>>>>>>>>>>>>>>>>>>>>>>>>>>>process_ptrace_info: thread = %d\n", GETTID()));
1214
1215 // TODO: consider that only checkpoint thread now runs this code
1216 // if (thread == motherofall) {
1217 // read the information from the ptrace file
1218 ptrace_fd = open(ptrace_shared_file, O_RDONLY);
1219 if (ptrace_fd != -1) {
1220 *has_ptrace_file = 1;
1221 while (readall(ptrace_fd, &superior, sizeof(pid_t)) > 0) {
1222 readall(ptrace_fd, &inferior, sizeof(pid_t));
1223 if ( is_in_ptrace_pairs(superior, inferior) == -1 ) {
1224 add_to_ptrace_pairs(superior, inferior, PTRACE_UNSPECIFIED_COMMAND, FALSE);
1225 }
1226 if (*delete_ptrace_leader < superior)
1227 *delete_ptrace_leader = superior;
1228 }
1229 if ( close(ptrace_fd) != 0 ) {
1230 mtcp_printf("process_ptrace_info: Error closing file. Error: %s\n", strerror(errno));
1231 mtcp_abort();
1232 }
1233
1234 /* delete all dead threads */
1235 for (i = 0; i < ptrace_pairs_count; i++) {
1236 if ((!is_alive(ptrace_pairs[i].superior) || !is_alive(ptrace_pairs[i].inferior))
1237 &&
1238 (ptrace_pairs[i].eligible_for_deletion == TRUE)) {
1239 if ( i != (ptrace_pairs_count - 1)) {
1240 temp = ptrace_pairs[i];
1241 ptrace_pairs[i] = ptrace_pairs[ptrace_pairs_count - 1];
1242 ptrace_pairs[ptrace_pairs_count - 1] = temp;
1243 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
1244 i--;
1245 ptrace_pairs_count --;
1246 }
1247 else {
1248 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
1249 ptrace_pairs_count --;
1250 break;
1251 }
1252 }
1253 }
1254
1255 /* none of the eligible for deletion entries can be deleted anymore */
1256 for (i = 0; i < ptrace_pairs_count; i++) {
1257 /* SHOULDN'T "=" BE REPLACED BY "==" IN IF CONDITION? - Gene */
1258 if (ptrace_pairs[i].eligible_for_deletion = TRUE)
1259 ptrace_pairs[i].eligible_for_deletion = FALSE;
1260 }
1261 }
1262 else mtcp_printf("process_ptrace_info: NO ptrace file\n");
1263
1264 // read the information from the setoptions file
1265 setoptions_fd = open(ptrace_setoptions_file, O_RDONLY);
1266 if (setoptions_fd != -1) {
1267 *has_setoptions_file = 1;
1268 while (readall(setoptions_fd, &superior, sizeof(pid_t)) > 0) {
1269 readall(setoptions_fd, &inferior, sizeof(pid_t));
1270 if (inferior == GETTID()) {
1271 setoptions_superior = superior;
1272 is_ptrace_setoptions = TRUE;
1273 }
1274 if (*delete_setoptions_leader < superior)
1275 *delete_setoptions_leader = superior;
1276 }
1277 if ( close(setoptions_fd) != 0 ) {
1278 mtcp_printf("process_ptrace_info: Error closing file: %s\n", strerror(errno));
1279 mtcp_abort();
1280 }
1281 }
1282 else mtcp_printf ("process_ptrace_info: NO setoptions file\n");
1283
1284 // read the information from the checkpoint threads file
1285 /* GDB specific code */
1286 checkpoint_fd = open(checkpoint_threads_file, O_RDONLY);
1287 if (checkpoint_fd != -1) {
1288 *has_checkpoint_file = 1;
1289 while (readall(checkpoint_fd, &pid, sizeof(pid_t)) > 0) {
1290 readall(checkpoint_fd, &tid, sizeof(pid_t));
1291 DPRINTF(("{%d} checkpoint threads: pid = %d tid = %d\n", GETTID(), pid, tid));
1292 if (is_alive(pid) && is_alive(tid)) {
1293 /* only the pid matters
1294 * for the first alive tid & pid, then tid is the ckpt of pid
1295 */
1296 if (!is_in_ckpt_threads(pid)) {
1297 ckpt_thread_temp.pid = pid;
1298 ckpt_thread_temp.tid = tid;
1299 ckpt_threads[ckpt_threads_count] = ckpt_thread_temp;
1300 ckpt_threads_count++;
1301 }
1302 if (*delete_checkpoint_leader < pid)
1303 *delete_checkpoint_leader = pid;
1304 }
1305 }
1306 if ( close(checkpoint_fd) != 0 ) {
1307 mtcp_printf("process_ptrace_info: Error closing file: %s\n", strerror(errno));
1308 mtcp_abort();
1309 }
1310 }
1311 else mtcp_printf("process_ptrace_info: NO checkpoint file\n");
1312
1313 sort_ptrace_pairs ();
1314
1315 print_ptrace_pairs ();
1316
1317 print_ckpt_threads ();
1318
1319 // We dont need sem_post anymore because this function is only called by checkpoint thread
1320 // TODO: remove semaphor-related stuff
1321
1322 /* allow all other threads to proceed
1323 * for all the threads excluding motherofall and checkpoint thread */
1324 /*
1325 for (loopthread = threads; loopthread != NULL && loopthread->next != NULL && loopthread->next->next != NULL;
1326 loopthread = loopthread->next) {
1327 sem_post(&ptrace_read_pairs_sem);
1328
1329 }
1330 }else
1331 // all threads with the exception of motherofall (checkpoint thread does NOT run this code) wait for motherofall to write
1332 // the info from the ptrace file to memory (shared among all threads of a process)
1333 sem_wait(&ptrace_read_pairs_sem);
1334 */
1335
1336 }
1337
1338 static int is_checkpoint_thread (pid_t tid)
1339 {
1340 int i;
1341 for (i = 0; i < ckpt_threads_count; i++) {
1342 if (ckpt_threads[i].tid == tid ) return ckpt_threads[i].pid;
1343 }
1344 return 0;
1345 }
1346
1347 static int ptrace_detach_ckpthread(pid_t tgid, pid_t tid, pid_t supid)
1348 {
1349 int status;
1350 char pstate;
1351 pid_t tpid;
1352
1353 DPRINTF(("detach_ckpthread: tid=%d, tgid = %d >>>>>>>>>>>>>>>>>>\n", tid, tgid));
1354
1355 pstate = procfs_state(tid);
1356 DPRINTF(("detach_ckpthread: CKPT Thread procfs_state(%d) = %c\n", tid, pstate));
1357 if( pstate == 0 ){
1358 // such process not exist
1359 return -ENOENT;
1360 }else if (pstate == 'T') {
1361 // There can be posibility that GDB (or other) reads status of this
1362 // thread before us. So we will block. We don't want that. // Read anyway but without hang
1363 DPRINTF(("detach_ckpthread: Checkpoint thread already stopped\n"));
1364
1365 is_waitpid_local = 1;
1366 tpid = waitpid(tid, &status, WNOHANG);
1367 if (tpid == -1 && errno == ECHILD) {
1368 DPRINTF(("detach_ckpthread: Check cloned process\n"));
1369 // Try again with __WCLONE to check cloned processes.
1370 is_waitpid_local = 1;
1371 if ((tpid = waitpid(tid, &status, __WCLONE | WNOHANG)) == -1) {
1372 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n"
1373 ,
1374 strerror(errno)));
1375 }
1376 }
1377 DPRINTF(("detach_ckpthread: tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
1378 tid, tpid, WIFSTOPPED(status),
1379 WSTOPSIG(status) == SIGSTOP, WSTOPSIG(status)));
1380 }else{
1381 /*
1382 * and if inferior is a checkpoint thread
1383 */
1384 if (kill(tid, SIGSTOP) == -1) {
1385 mtcp_printf("detach_ckpthread: ptrace_detach_checkpoint_threads: kill: %s\n",
1386 strerror(errno));
1387 return -EAGAIN;
1388 }
1389 is_waitpid_local = 1;
1390 tpid = waitpid(tid, &status, 0);
1391 DPRINTF(("detach_ckpthread: tpid1=%d,errno=%d,ECHILD=%d\n", tpid, errno, ECHILD));
1392 if ((tpid) == -1 && errno == ECHILD) {
1393 DPRINTF(("detach_ckpthread: Check cloned process\n"));
1394 /*
1395 * Try again with __WCLONE to check cloned processes.
1396 */
1397 is_waitpid_local = 1;
1398 if ((tpid = waitpid(tid, &status, __WCLONE)) == -1) {
1399 mtcp_printf("detach_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
1400 strerror(errno));
1401 return -EAGAIN;
1402 }
1403 }
1404 }
1405 DPRINTF(("detach_ckpthread: tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,"
1406 "signal=%d,err=%s\n",
1407 tid, tpid, WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,
1408 WSTOPSIG(status), strerror(errno)));
1409 if (WIFSTOPPED(status)) {
1410 if (WSTOPSIG(status) == SIGSTOP)
1411 DPRINTF(("detach_ckpthread: checkpoint thread %d was stopped by the delivery of SIGSTOP\n",tid));
1412 else { // we should never get here
1413 DPRINTF(("detach_ckpthread: checkpoint thread %d was stopped by the delivery of %d\n",
1414 tid,WSTOPSIG(status)));
1415 }
1416 } else // we should never end up here
1417 DPRINTF(("detach_ckpthread: checkpoint thread %d was NOT stopped by a signal\n", tid));
1418
1419 is_ptrace_local = 1;
1420 if (ptrace(PTRACE_DETACH, tid, 0, SIGCONT) == -1) {
1421 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: parent = %d child = %d\n",
1422 supid, tid));
1423 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: PTRACE_DETACH failed: %s\n",
1424 strerror(errno)));
1425 return -EAGAIN;
1426 }
1427
1428 DPRINTF(("detach_ckpthread: tid=%d, tgid = %d <<<<<<<<<<<<<<<<<<<<<<<<<<\n", tid, tgid));
1429 only_once = 0; /* no need for semaphore here - the UT execute this code */
1430 return 0;
1431 }
1432
1433 static int ptrace_control_ckpthread(pid_t tgid, pid_t tid)
1434 {
1435 int status;
1436 char pstate;
1437 pid_t tpid;
1438
1439 DPRINTF(("control_ckpthread: tid=%d, tgid = %d >>>>>>>>>>>>>>>>>>>>>>>\n", tid, tgid));
1440
1441 pstate = procfs_state(tid);
1442 DPRINTF(("control_ckpthread: CKPT Thread procfs_state(%d) = %c\n", tid, pstate));
1443
1444 if( pstate == 0 ){
1445 // process not exist
1446 return -ENOENT;
1447 }else if( pstate == 'T') {
1448 // There can be posibility that GDB (or other) reads status of this
1449 // thread before us. So we will block. We don't want that.
1450 // Read anyway but without hang
1451 DPRINTF(("control_ckpthread: Checkpoint thread stopped by controlled debugger\n"));
1452
1453 if( mtcp_sys_kernel_tkill(tid,SIGCONT) )
1454 return -EAGAIN;
1455
1456 DPRINTF(("control_ckpthread: Check cloned process\n"));
1457 // Try again with __WCLONE to check cloned processes.
1458 is_waitpid_local = 1;
1459 if ((tpid = waitpid(tid, &status, __WCLONE | WNOHANG)) == -1) {
1460 mtcp_printf("control_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
1461 strerror(errno));
1462 return -EAGAIN;
1463 }
1464
1465 DPRINTF(("control_ckpthread: tgid = %d, tpid=%d,continued=%d,err=%s\n",
1466 tid, tpid, WIFCONTINUED(status), strerror(errno)));
1467
1468 if( WIFCONTINUED(status) ) {
1469 DPRINTF(("control_ckpthread: checkpoint thread %d was stopped by the delivery of SIGSTOP\n",tid));
1470 }else{ // we should never end up here
1471 DPRINTF(("control_ckpthread: checkpoint thread %d was NOT stopped by a signal\n", tid));
1472 }
1473 }
1474
1475 DPRINTF(("control_ckpthread: tid=%d, tgid = %d <<<<<<<<<<<<<<<<<<<<<<<<<<\n", tid, tgid));
1476 return 0;
1477 }
1478
1479 void ptrace_save_threads_state ()
1480 {
1481 int i;
1482
1483 DPRINTF((">>>>>>>>> start ptrace_save_threads_state %d\n", GETTID()));
1484
1485 for(i = 0; i < ptrace_pairs_count; i++) {
1486 /*
1487 if( is_checkpoint_thread(ptrace_pairs[i].inferior) ){
1488 mtcp_printf("ptrace_detach_user_threads: SKIP checkpoint thread %d\n",ptrace_pairs[i].inferior);
1489 continue;
1490 }
1491 */
1492 //if( ptrace_pairs[i].superior == GETTID()){
1493 char pstate;
1494 int tid = ptrace_pairs[i].inferior;
1495 pstate = procfs_state(tid);
1496 DPRINTF(("save state of thread %d = %c\n",tid,pstate));
1497 ptrace_pairs[i].inferior_st = pstate;
1498 //}
1499 }
1500 DPRINTF((">>>>>>>>> done ptrace_save_threads_state %d\n", GETTID()));
1501 }
1502
1503 #endif