*** cygwin DLL Changes:
* child_info.h (CURR_CHILD_INFO_MAGIC): Reset. (child_info::dwProcessId): Delete. (child_info::straced): New variable. (child_info::handle_fork): New member function. * dcrt0.cc (in_forkee): New global variable. (__cygwin_user_data::forkee): Mark as obsolete. (do_global_ctors): Use in_forkee rather than user_data->forkee. (get_cygwin_startup_info): Ditto. Deal with new straced field to allow strace to deal with children of attached processes. (initial_env): Accommodate changes to strace::hello. (child_info_fork::handle_fork): Rename from plain old 'handle_fork'. Move alloc_stack() call elsewhere. (dll_crt0_0): Fill out more of user_data. Reference handle_fork via fork_info. Add some debugging output. (_dll_crt0): Don't wait for sync thread if sync_startup is invalid. Zero sync_startup here. Call alloc_stack() here, if appropriate. (dll_crt0_1): Use in_forkee rather than user_data->forkee. (dll_crt0): Ditto. * malloc_wrapper.cc (malloc_init): Ditto. * dll_init.cc (in_forkee): Remove local static version of this variable. (dll_list::load_after_fork): Don't set in_forkee here. * external.cc (cygwin_internal): Use strace method rather than accessing field directly. * fhandler.cc (fhandler_base::read): Ditto. * fhandler_tty.cc (fhandler_tty_common::__acquire_output_mutex): Ditto. * fork.cc (frok::parent): Invoke strace write_childpid to communicate with potential strace. (child_copy): Add more detail to debugging output. * init.cc (calibration_id): New static variable. (prime_threads): Set sync_startup to invalid handle if we already know about thread_func_ix. Use static calibration_id to hold calibration thread id. * munge_threadfunc (munge_threadfunc): Don't try to debug if we don't find threadfunc_ix. (dll_entry): Avoid calling munge_threadfunc and _cygtls::remove on non-cygwin threads invoked during process startup. * pinfo.cc (set_myself): Always call strace.hello here regardless of DEBUGGING. * sigproc.cc (child_info::child_info): Remove spurious handling of dwProcessId. Set straced as appropriate. * spawn.cc (spawn_guts): Rename ciresrv to ch. Invoke strace write_childpid to communicate with potential strace. * strace.cc: Include child_info.h. (strace::hello): Remove inited test. Use active() method to test if strace has been activated. Handle case where we are started before (mypid): New function. (strace::vsprntf): Try to deal more intelligently with case where progname may not be filled out. Put pid in parentheses if it is a windows pid rather than a cygwin pid. myself has been filled out. (strace::write_childpid): New function for notifying strace about the creation of children. (strace::vprntf): Use strace method rather than accessing field directly. (strace_printf): Ditto. (strace::wm): Ditto. * winsup.h (in_forkee): Declare. * include/sys/strace.h (strace::write_childpid): Declare new function. (strace::attached): Define new function. (strace::active): Ditto. (strace::active_val): Ditto. (_STRACE_ON): Delete. (_STRACE_OFF): Ditto. (define_strace0): Use strace method rather than accessing field directly. (strace_printf_wrap): Ditto. (strace_printf_wrap1): Ditto. *** cygwin utils changes: * strace.cc (nprocesses): Make static global. (quiet): New variable. (strace_active): Ditto. (add_child): Increment nprocesses here. Don't add a child if it is already added (windows bug?). Report on child if not quiet. (get_child): Just return NULL if child not found. (remove_child): Report on child if not quiet. (attach_process): Don't complain if given a windows process. Use windows pid in error. (handle_output_debug_string): Issue error if trying to manipulate a process that we don't know about. Handle _STRACE_CHILD_PID - attach to reported child when we get this. (proc_child): Move nprocesses to file scope. Report on exceptions. (longopts): Implement "--quiet". (opts): Implement "-q". (main): Manipulate quiet flag. * utils.sgml (strace): Add words describing '-q'.
This commit is contained in:
@@ -37,11 +37,15 @@ static int forkdebug = 1;
|
||||
static int numerror = 1;
|
||||
static int show_usecs = 1;
|
||||
static int delta = 1;
|
||||
static int hhmmss = 0;
|
||||
static int bufsize = 0;
|
||||
static int new_window = 0;
|
||||
static long flush_period = 0;
|
||||
static int include_hex = 0;
|
||||
static int hhmmss;
|
||||
static int bufsize;
|
||||
static int new_window;
|
||||
static long flush_period;
|
||||
static int include_hex;
|
||||
static int quiet = -1;
|
||||
|
||||
static unsigned char strace_active = 1;
|
||||
static int processes;
|
||||
|
||||
static BOOL close_handle (HANDLE h, DWORD ok);
|
||||
|
||||
@@ -104,18 +108,6 @@ error (int geterrno, const char *fmt, ...)
|
||||
DWORD lastid = 0;
|
||||
HANDLE lasth;
|
||||
|
||||
#define PROCFLAGS \
|
||||
PROCESS_ALL_ACCESS /*(PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_VM_READ | PROCESS_VM_WRITE) */
|
||||
static void
|
||||
add_child (DWORD id, HANDLE hproc)
|
||||
{
|
||||
child_list *c = children.next;
|
||||
children.next = (child_list *) calloc (1, sizeof (child_list));
|
||||
children.next->next = c;
|
||||
lastid = children.next->id = id;
|
||||
lasth = children.next->hproc = hproc;
|
||||
}
|
||||
|
||||
static child_list *
|
||||
get_child (DWORD id)
|
||||
{
|
||||
@@ -124,7 +116,23 @@ get_child (DWORD id)
|
||||
if (c->id == id)
|
||||
return c;
|
||||
|
||||
error (0, "no process id %d found", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
add_child (DWORD id, HANDLE hproc)
|
||||
{
|
||||
if (!get_child (id))
|
||||
{
|
||||
child_list *c = children.next;
|
||||
children.next = (child_list *) calloc (1, sizeof (child_list));
|
||||
children.next->next = c;
|
||||
lastid = children.next->id = id;
|
||||
lasth = children.next->hproc = hproc;
|
||||
processes++;
|
||||
if (!quiet)
|
||||
fprintf (stderr, "Windows process %d attached\n", id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,6 +147,9 @@ remove_child (DWORD id)
|
||||
child_list *c1 = c->next;
|
||||
c->next = c1->next;
|
||||
free (c1);
|
||||
if (!quiet)
|
||||
fprintf (stderr, "Windows process %d detached\n", id);
|
||||
processes--;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -283,15 +294,11 @@ attach_process (pid_t pid)
|
||||
{
|
||||
child_pid = (DWORD) cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
|
||||
if (!child_pid)
|
||||
{
|
||||
warn (0, "no such cygwin pid - %d", pid);
|
||||
child_pid = pid;
|
||||
}
|
||||
child_pid = pid;
|
||||
|
||||
if (!DebugActiveProcess (child_pid))
|
||||
error (0, "couldn't attach to pid %d<%d> for debugging", pid, child_pid);
|
||||
error (0, "couldn't attach to pid %d for debugging", child_pid);
|
||||
|
||||
printf ("Attached to pid %d (windows pid %u)\n", pid, (unsigned) child_pid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -396,6 +403,8 @@ handle_output_debug_string (DWORD id, LPVOID p, unsigned mask, FILE *ofile)
|
||||
char alen[3 + 8 + 1];
|
||||
DWORD nbytes;
|
||||
child_list *child = get_child (id);
|
||||
if (!child)
|
||||
error (0, "no process id %d found", id);
|
||||
HANDLE hchild = child->hproc;
|
||||
#define INTROLEN (sizeof (alen) - 1)
|
||||
|
||||
@@ -423,7 +432,7 @@ handle_output_debug_string (DWORD id, LPVOID p, unsigned mask, FILE *ofile)
|
||||
else
|
||||
{
|
||||
special = len;
|
||||
if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
|
||||
if (special == _STRACE_INTERFACE_ACTIVATE_ADDR || special == _STRACE_CHILD_PID)
|
||||
len = 17;
|
||||
}
|
||||
|
||||
@@ -441,14 +450,20 @@ handle_output_debug_string (DWORD id, LPVOID p, unsigned mask, FILE *ofile)
|
||||
|
||||
s = strchr (s, '\0') + 1;
|
||||
|
||||
if (special == _STRACE_CHILD_PID)
|
||||
{
|
||||
if (!DebugActiveProcess (n))
|
||||
error (0, "couldn't attach to subprocess %d for debugging, "
|
||||
"windows error %d", n, GetLastError ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (special == _STRACE_INTERFACE_ACTIVATE_ADDR)
|
||||
{
|
||||
DWORD new_flag = 1;
|
||||
if (!WriteProcessMemory (hchild, (LPVOID) n, &new_flag,
|
||||
sizeof (new_flag), &nbytes))
|
||||
error (0,
|
||||
"couldn't write strace flag to subprocess at %p, windows error %d",
|
||||
n, GetLastError ());
|
||||
if (!WriteProcessMemory (hchild, (LPVOID) n, &strace_active,
|
||||
sizeof (strace_active), &nbytes))
|
||||
error (0, "couldn't write strace flag to subprocess at %p, "
|
||||
"windows error %d", n, GetLastError ());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -577,7 +592,6 @@ static void
|
||||
proc_child (unsigned mask, FILE *ofile, pid_t pid)
|
||||
{
|
||||
DEBUG_EVENT ev;
|
||||
int processes = 0;
|
||||
time_t cur_time, last_time;
|
||||
|
||||
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
|
||||
@@ -609,7 +623,6 @@ proc_child (unsigned mask, FILE *ofile, pid_t pid)
|
||||
if (ev.u.CreateProcessInfo.hFile)
|
||||
CloseHandle (ev.u.CreateProcessInfo.hFile);
|
||||
add_child (ev.dwProcessId, ev.u.CreateProcessInfo.hProcess);
|
||||
processes++;
|
||||
break;
|
||||
|
||||
case CREATE_THREAD_DEBUG_EVENT:
|
||||
@@ -630,22 +643,20 @@ proc_child (unsigned mask, FILE *ofile, pid_t pid)
|
||||
remove_child (ev.dwProcessId);
|
||||
break;
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
if (ev.u.Exception.ExceptionRecord.ExceptionCode !=
|
||||
STATUS_BREAKPOINT)
|
||||
if (ev.u.Exception.ExceptionRecord.ExceptionCode != STATUS_BREAKPOINT)
|
||||
{
|
||||
status = DBG_EXCEPTION_NOT_HANDLED;
|
||||
#if 0
|
||||
fprintf (stderr, "exception %p at %p\n",
|
||||
ev.u.Exception.ExceptionRecord.ExceptionCode,
|
||||
ev.u.Exception.ExceptionRecord.ExceptionAddress);
|
||||
#endif
|
||||
if (ev.u.Exception.dwFirstChance)
|
||||
fprintf (ofile, "--- Process %u, exception %p at %p\n", ev.dwProcessId,
|
||||
ev.u.Exception.ExceptionRecord.ExceptionCode,
|
||||
ev.u.Exception.ExceptionRecord.ExceptionAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!ContinueDebugEvent (ev.dwProcessId, ev.dwThreadId, status))
|
||||
error (0, "couldn't continue debug event, windows error %d",
|
||||
GetLastError ());
|
||||
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT && --processes == 0)
|
||||
if (!processes)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -864,6 +875,7 @@ struct option longopts[] = {
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"no-delta", no_argument, NULL, 'd'},
|
||||
{"pid", required_argument, NULL, 'p'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"timestamp", no_argument, NULL, 't'},
|
||||
{"toggle", no_argument, NULL, 'T'},
|
||||
{"trace-children", no_argument, NULL, 'f'},
|
||||
@@ -873,7 +885,7 @@ struct option longopts[] = {
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
static const char *const opts = "+b:dhHfm:no:p:S:tTuvw";
|
||||
static const char *const opts = "+b:dhHfm:no:p:qS:tTuvw";
|
||||
|
||||
static void
|
||||
print_version ()
|
||||
@@ -906,6 +918,7 @@ main (int argc, char **argv)
|
||||
pid_t pid = 0;
|
||||
int opt;
|
||||
int toggle = 0;
|
||||
int sawquiet = -1;
|
||||
|
||||
if (load_cygwin ())
|
||||
{
|
||||
@@ -963,6 +976,13 @@ character #%d.\n", optarg, (int) (endptr - optarg), endptr);
|
||||
break;
|
||||
case 'p':
|
||||
pid = strtoul (optarg, NULL, 10);
|
||||
strace_active |= 2;
|
||||
break;
|
||||
case 'q':
|
||||
if (sawquiet < 0)
|
||||
sawquiet = 1;
|
||||
else
|
||||
sawquiet ^= 1;
|
||||
break;
|
||||
case 'S':
|
||||
flush_period = strtoul (optarg, NULL, 10);
|
||||
@@ -999,6 +1019,13 @@ character #%d.\n", optarg, (int) (endptr - optarg), endptr);
|
||||
if (toggle && !pid)
|
||||
error (0, "must provide a process id to toggle tracing");
|
||||
|
||||
if (!pid)
|
||||
quiet = sawquiet < 0 || !sawquiet;
|
||||
else if (sawquiet < 0)
|
||||
quiet = 0;
|
||||
else
|
||||
quiet = sawquiet;
|
||||
|
||||
if (!mask)
|
||||
mask = _STRACE_ALL;
|
||||
|
||||
|
Reference in New Issue
Block a user