static void run_target(char** argv) { static struct itimerval it; int status = 0; if (!quiet_mode) SAYF("-- Program output begins --\n" cRST); MEM_BARRIER(); child_pid = fork(); if (child_pid < 0) PFATAL("fork() failed"); if (!child_pid) { struct rlimit r; if (quiet_mode) { s32 fd = open("/dev/null", O_RDWR); if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) { *(u32*)trace_bits = EXEC_FAIL_SIG; PFATAL("Descriptor initialization failed"); } close(fd); } if (mem_limit) { r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; #ifdef RLIMIT_AS setrlimit(RLIMIT_AS, &r); /* Ignore errors */ #else setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ #endif /* ^RLIMIT_AS */ } r.rlim_max = r.rlim_cur = 0; setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ execv(target_path, argv); *(u32*)trace_bits = EXEC_FAIL_SIG; exit(0); } /* Configure timeout, wait for child, cancel timeout. */ if (exec_tmout) { child_timed_out = 0; it.it_value.tv_sec = (exec_tmout / 1000); it.it_value.tv_usec = (exec_tmout % 1000) * 1000; } setitimer(ITIMER_REAL, &it, NULL); if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); child_pid = 0; it.it_value.tv_sec = 0; it.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &it, NULL); MEM_BARRIER(); /* Clean up bitmap, analyze exit condition, etc. */ if (*(u32*)trace_bits == EXEC_FAIL_SIG) FATAL("Unable to execute '%s'", argv[0]); classify_counts(trace_bits); if (!quiet_mode) SAYF(cRST "-- Program output ends --\n"); if (!child_timed_out && !stop_soon && WIFSIGNALED(status)) child_crashed = 1; if (!quiet_mode) { if (child_timed_out) SAYF(cLRD "\n+++ Program timed off +++\n" cRST); else if (stop_soon) SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); else if (child_crashed) SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status)); } }
/* * Entry point for JDWP thread. The thread was created through the VM * mechanisms, so there is a java/lang/Thread associated with us. */ static void* jdwpThreadStart(void* arg) { JdwpState* state = (JdwpState*) arg; LOGV("JDWP: thread running\n"); /* * Finish initializing "state", then notify the creating thread that * we're running. */ state->debugThreadHandle = dvmThreadSelf()->handle; state->run = true; MEM_BARRIER(); state->debugThreadStarted = true; // touch this last dvmDbgLockMutex(&state->threadStartLock); dvmDbgCondBroadcast(&state->threadStartCond); dvmDbgUnlockMutex(&state->threadStartLock); /* set the thread state to VMWAIT so GCs don't wait for us */ dvmDbgThreadWaiting(); /* * Loop forever if we're in server mode, processing connections. In * non-server mode, we bail out of the thread when the debugger drops * us. * * We broadcast a notification when a debugger attaches, after we * successfully process the handshake. */ while (state->run) { bool first; int cc; if (state->params.server) { /* * Block forever, waiting for a connection. To support the * "timeout=xxx" option we'll need to tweak this. */ if (!dvmJdwpAcceptConnection(state)) break; } else { /* * If we're not acting as a server, we need to connect out to the * debugger. To support the "timeout=xxx" option we need to * have a timeout if the handshake reply isn't received in a * reasonable amount of time. */ if (!dvmJdwpEstablishConnection(state)) { /* wake anybody who was waiting for us to succeed */ dvmDbgLockMutex(&state->attachLock); dvmDbgCondBroadcast(&state->attachCond); dvmDbgUnlockMutex(&state->attachLock); break; } } /* prep debug code to handle the new connection */ dvmDbgConnected(); /* process requests until the debugger drops */ first = true; while (true) { // sanity check -- shouldn't happen? if (dvmThreadSelf()->status != THREAD_VMWAIT) { LOGE("JDWP thread no longer in VMWAIT (now %d); resetting\n", dvmThreadSelf()->status); dvmDbgThreadWaiting(); } if (!dvmJdwpProcessIncoming(state)) /* blocking read */ break; if (first && !dvmJdwpAwaitingHandshake(state)) { /* handshake worked, tell the interpreter that we're active */ first = false; /* set thread ID; requires object registry to be active */ state->debugThreadId = dvmDbgGetThreadSelfId(); /* wake anybody who's waiting for us */ dvmDbgLockMutex(&state->attachLock); dvmDbgCondBroadcast(&state->attachCond); dvmDbgUnlockMutex(&state->attachLock); } } dvmJdwpCloseConnection(state); if (state->ddmActive) { state->ddmActive = false; /* broadcast the disconnect; must be in RUNNING state */ dvmDbgThreadRunning(); dvmDbgDdmDisconnected(); dvmDbgThreadWaiting(); } /* interpreter can ignore breakpoints */ dvmDbgDisconnected(); /* if we had stuff suspended, resume it now */ dvmUndoDebuggerSuspensions(); dvmJdwpResetState(state); /* if we connected out, this was a one-shot deal */ if (!state->params.server) state->run = false; } /* back to running, for thread shutdown */ dvmDbgThreadRunning(); LOGV("JDWP: thread exiting\n"); return NULL; }