diff options
author | Christopher Faylor <me@cgf.cx> | 2005-12-29 20:46:34 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2005-12-29 20:46:34 +0000 |
commit | 5d97040501505d37b01268fdf335ef6ea2bafb44 (patch) | |
tree | 2764464e535cc8ec94122a853743e5583f2b0c95 | |
parent | 10e4168d8441980eeec3a5d3ce7f5a6052c3ee27 (diff) | |
download | newlib-5d97040501505d37b01268fdf335ef6ea2bafb44.zip newlib-5d97040501505d37b01268fdf335ef6ea2bafb44.tar.gz newlib-5d97040501505d37b01268fdf335ef6ea2bafb44.tar.bz2 |
*** 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'.
-rw-r--r-- | winsup/cygwin/ChangeLog | 70 | ||||
-rw-r--r-- | winsup/cygwin/child_info.h | 5 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/dcrt0.cc | 64 | ||||
-rw-r--r-- | winsup/cygwin/dll_init.cc | 4 | ||||
-rw-r--r-- | winsup/cygwin/external.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_tty.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/fork.cc | 6 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/strace.h | 31 | ||||
-rw-r--r-- | winsup/cygwin/init.cc | 19 | ||||
-rw-r--r-- | winsup/cygwin/malloc_wrapper.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/pinfo.cc | 5 | ||||
-rw-r--r-- | winsup/cygwin/sigproc.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/spawn.cc | 20 | ||||
-rw-r--r-- | winsup/cygwin/strace.cc | 87 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 1 | ||||
-rw-r--r-- | winsup/utils/ChangeLog | 20 | ||||
-rw-r--r-- | winsup/utils/strace.cc | 111 | ||||
-rw-r--r-- | winsup/utils/utils.sgml | 2 |
20 files changed, 314 insertions, 143 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6e8d91c..39317a2 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,73 @@ +2005-12-29 Christopher Faylor <cgf@timesys.com> + + * 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. + 2005-12-28 Christopher Faylor <cgf@timesys.com> * environ.cc (win_env::add_cache): Don't add variables to the diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h index 7442e1c..9e6433d 100644 --- a/winsup/cygwin/child_info.h +++ b/winsup/cygwin/child_info.h @@ -29,7 +29,7 @@ enum child_info_types #define EXEC_MAGIC_SIZE sizeof(child_info) -#define CURR_CHILD_INFO_MAGIC 0xb530a54dU +#define CURR_CHILD_INFO_MAGIC 0xc87757a7U /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between @@ -48,7 +48,7 @@ public: init_cygheap *cygheap; void *cygheap_max; DWORD cygheap_reserve_sz; - DWORD dwProcessId; + unsigned char straced; unsigned fhandler_union_cb; child_info (unsigned, child_info_types, bool); child_info (): subproc_ready (NULL), parent (NULL) {} @@ -69,6 +69,7 @@ public: void *stacktop; // location of top of parent stack void *stackbottom; // location of bottom of parent stack child_info_fork (); + void handle_fork (); }; class fhandler_base; diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 03d1777..e27fe1e 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -147,7 +147,7 @@ void _cygtls::remove (DWORD wait) { debug_printf ("wait %p", wait); - if (!locals.exitsock || exit_state >= ES_FINAL) + if (1 || !isinitialized () || !locals.exitsock || exit_state >= ES_FINAL) return; if (wait) { diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 6e0b765..04bef6e 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -53,6 +53,7 @@ muto NO_COPY lock_process::locker; bool display_title; bool strip_title_path; bool allow_glob = true; +bool NO_COPY in_forkee; codepage_type current_codepage = ansi_cp; int __argc_safe; @@ -108,7 +109,7 @@ extern "C" /* premain */ {NULL, NULL, NULL, NULL}, /* run_ctors_p */ 0, /* unused */ {0, 0, 0, 0, 0, 0, 0}, - /* forkee */ 0, + /* UNUSED forkee */ 0, /* hmodule */ NULL, /* api_major */ CYGWIN_VERSION_API_MAJOR, /* api_minor */ CYGWIN_VERSION_API_MINOR, @@ -141,7 +142,7 @@ do_global_dtors () static void __stdcall do_global_ctors (void (**in_pfunc)(), int force) { - if (!force && user_data->forkee) + if (!force && in_forkee) return; // inherit constructed stuff from parent pid /* Run ctors backwards, so skip the first entry and find how many @@ -554,11 +555,8 @@ initial_env () len = GetModuleFileName (NULL, buf, CYG_MAX_PATH); console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf); Sleep (ms); - if (!strace.active && !dynamically_loaded) - { - strace.inited = 0; - strace.hello (); - } + if (!strace.active () && !dynamically_loaded) + strace.hello (); } if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1)) { @@ -611,7 +609,7 @@ get_cygwin_startup_info () switch (res->type) { case _PROC_FORK: - user_data->forkee = true; + in_forkee = true; should_be_cb = sizeof (child_info_fork); /* fall through */; case _PROC_SPAWN: @@ -622,6 +620,20 @@ get_cygwin_startup_info () multiple_cygwin_problem ("proc size", res->cb, should_be_cb); else if (sizeof (fhandler_union) != res->fhandler_union_cb) multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union)); + if (res->straced) + { + res->ready (false); +#if 0 + DWORD prio = GetThreadPriority (GetCurrentThread ()); + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE); +#endif + for (unsigned i = 0; !being_debugged () && i < 10000; i++) + low_priority_sleep (0); +#if 0 + SetThreadPriority (GetCurrentThread (), prio); +#endif + strace.hello (); + } break; default: system_printf ("unknown exec type %d", res->type); @@ -641,26 +653,24 @@ get_cygwin_startup_info () #define dll_bss_end &_bss_end__ void -handle_fork () +child_info_fork::handle_fork () { - alloc_stack (fork_info); cygheap_fixup_in_child (false); memory_init (); set_myself (NULL); - HANDLE hp = fork_info->parent; - child_copy (hp, false, + child_copy (parent, false, "dll data", dll_data_start, dll_data_end, "dll bss", dll_bss_start, dll_bss_end, "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr, NULL); /* step 2 now that the dll has its heap filled in, we can fill in the user's data and bss since user_data is now filled out. */ - child_copy (hp, false, + child_copy (parent, false, "data", user_data->data_start, user_data->data_end, "bss", user_data->bss_start, user_data->bss_end, NULL); - if (fixup_mmaps_after_fork (hp)) + if (fixup_mmaps_after_fork (parent)) api_fatal ("recreate_mmaps_after_fork_failed"); } @@ -675,6 +685,8 @@ dll_crt0_0 () _impure_ptr->_stdout = &_impure_ptr->__sf[1]; _impure_ptr->_stderr = &_impure_ptr->__sf[2]; _impure_ptr->_current_locale = "C"; + user_data->impure_ptr = _impure_ptr; + user_data->impure_ptr_ptr = &_impure_ptr; wincap.init (); initial_env (); mmap_init (); @@ -690,7 +702,6 @@ dll_crt0_0 () OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken); SetErrorMode (SEM_FAILCRITICALERRORS); - device::init (); do_global_ctors (&__CTOR_LIST__, 1); cygthread::init (); @@ -704,7 +715,7 @@ dll_crt0_0 () switch (child_proc_info->type) { case _PROC_FORK: - handle_fork (); + fork_info->handle_fork (); break; case _PROC_SPAWN: case _PROC_EXEC: @@ -747,6 +758,7 @@ dll_crt0_0 () DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &hProcImpToken); + debug_printf ("finished dll_crt0_0 initialization"); } /* Take over from libc's crt0.o and start the application. Note the @@ -772,7 +784,7 @@ dll_crt0_1 (char *) /* Initialize pthread mainthread when not forked and it is safe to call new, otherwise it is reinitalized in fixup_after_fork */ - if (!user_data->forkee) + if (!in_forkee) pthread::init_mainthread (); #ifdef DEBUGGING @@ -791,7 +803,7 @@ dll_crt0_1 (char *) #endif cygbench ("pre-forkee"); - if (user_data->forkee) + if (in_forkee) { /* If we've played with the stack, stacksize != 0. That means that fork() was invoked from other than the main thread. Make sure that @@ -946,18 +958,15 @@ initialize_main_tls (char *padding) extern "C" void __stdcall _dll_crt0 () { + extern DWORD threadfunc_ix; extern HANDLE sync_startup; - extern unsigned threadfunc_ix; - if (threadfunc_ix) - /* nothing to do */; - else if (!sync_startup) - system_printf ("internal error: sync_startup not called at start. Expect signal problems."); - else + if (sync_startup != INVALID_HANDLE_VALUE) { WaitForSingleObject (sync_startup, INFINITE); CloseHandle (sync_startup); } + sync_startup = NULL; if (!threadfunc_ix) system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems."); @@ -968,8 +977,9 @@ _dll_crt0 () char padding[CYGTLS_PADSIZE]; - if (child_proc_info && child_proc_info->type == _PROC_FORK) - user_data->forkee = true; +debug_printf ("in_forkee %d, fork_info %p", in_forkee, fork_info); + if (in_forkee) + alloc_stack (fork_info); else __sinit (_impure_ptr); @@ -981,7 +991,7 @@ void dll_crt0 (per_process *uptr) { /* Set the local copy of the pointer into the user space. */ - if (!user_data->forkee && uptr && uptr != user_data) + if (!in_forkee && uptr && uptr != user_data) { memcpy (user_data, uptr, per_process_overwrite); *(user_data->impure_ptr_ptr) = _GLOBAL_REENT; diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index b394906..ecfc976 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -23,7 +23,6 @@ extern void __stdcall check_sanity_and_sync (per_process *); dll_list NO_COPY dlls; -static int NO_COPY in_forkee; static bool dll_global_dtors_recorded; /* Run destructors for all DLLs on exit. */ @@ -283,7 +282,6 @@ release_upto (const char *name, DWORD here) void dll_list::load_after_fork (HANDLE parent, dll *first) { - in_forkee = 1; int try2 = 0; dll d; @@ -346,7 +344,7 @@ dll_list::load_after_fork (HANDLE parent, dll *first) } next = d.next; /* Get the address of the next DLL. */ } - in_forkee = 0; + in_forkee = false; } extern "C" int diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index b51c58b..dc83f7b 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -218,7 +218,7 @@ cygwin_internal (cygwin_getinfo_types t, ...) case CW_STRACE_ACTIVE: { - return strace.active; + return strace.active (); } case CW_CYGWIN_PID_TO_WINPID: diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index e1686e1..6979a5c 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -772,7 +772,7 @@ fhandler_base::read (void *in_ptr, size_t& len) len = dst - (char *) ptr; #ifndef NOSTRACE - if (strace.active) + if (strace.active ()) { char buf[16 * 6 + 1]; char *p = buf; diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index f7afce0..6d95ab1 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -112,7 +112,7 @@ DWORD fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln, DWORD ms) { - if (strace.active) + if (strace.active ()) strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms); DWORD res = WaitForSingleObject (output_mutex, ms); if (res == WAIT_OBJECT_0) diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 31a5820..e4c3c31 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -307,12 +307,14 @@ frok::parent (void *stack_here) /* Fixup the parent datastructure if needed and resume the child's main thread. */ - if (cygheap->fdtab.need_fixup_before ()) + if (c_flags & CREATE_SUSPENDED) { cygheap->fdtab.fixup_before_fork (pi.dwProcessId); ResumeThread (pi.hThread); } + strace.write_childpid (ch, pi.dwProcessId); + child_pid = cygwin_pid (pi.dwProcessId); child.init (child_pid, 1, NULL); @@ -662,7 +664,7 @@ child_copy (HANDLE hp, bool write, ...) res = WriteProcessMemory (hp, here, here, todo, &done); else res = ReadProcessMemory (hp, here, here, todo, &done); - debug_printf ("hp %p, low %p, high %p, res %d", hp, low, high, res); + debug_printf ("%s - hp %p low %p, high %p, res %d", what, hp, low, high, res); if (!res || todo != done) { if (!res) diff --git a/winsup/cygwin/include/sys/strace.h b/winsup/cygwin/include/sys/strace.h index e54e76e..9b9da17 100644 --- a/winsup/cygwin/include/sys/strace.h +++ b/winsup/cygwin/include/sys/strace.h @@ -1,6 +1,7 @@ /* sys/strace.h - Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 Red Hat, Inc. This file is part of Cygwin. @@ -8,8 +9,6 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ -/* sys/strace.h */ - /* This file contains routines for tracing system calls and other internal phenomenon. @@ -33,21 +32,25 @@ details. */ #ifdef __cplusplus +class child_info; class strace { int vsprntf (char *buf, const char *func, const char *infmt, va_list ap); void write (unsigned category, const char *buf, int count); + unsigned char _active; public: int microseconds (); int version; - int active; int lmicrosec; - int execing; - int inited; - void hello (); + bool execing; + void hello () __attribute__ ((regparm (1))); void prntf (unsigned, const char *func, const char *, ...) /*__attribute__ ((regparm(3)))*/; void vprntf (unsigned, const char *func, const char *, va_list ap) /*__attribute__ ((regparm(3)))*/; void wm (int message, int word, int lon) __attribute__ ((regparm(3))); + void write_childpid (child_info&, unsigned long) __attribute__ ((regparm (2))); + bool attached () const {return _active == 3;} + bool active () const {return _active & 1;} + unsigned char& active_val () {return _active;} }; extern strace strace; @@ -56,6 +59,7 @@ extern strace strace; #define _STRACE_INTERFACE_ACTIVATE_ADDR -1 #define _STRACE_INTERFACE_ACTIVATE_ADDR1 -2 +#define _STRACE_CHILD_PID -3 /* Bitmasks of tracing messages to print. */ @@ -78,13 +82,6 @@ extern strace strace; #define _STRACE_MALLOC 0x20000 // trace malloc calls #define _STRACE_THREAD 0x40000 // thread-locking calls #define _STRACE_NOTALL 0x80000 // don't include if _STRACE_ALL -#if defined (DEBUGGING) -# define _STRACE_ON strace.active = 1 -# define _STRACE_OFF strace.active = 0 -#else -# define _STRACE_ON -# define _STRACE_OFF -#endif #ifdef __cplusplus extern "C" { @@ -108,7 +105,7 @@ void strace_printf (unsigned, const char *func, const char *, ...); #define define_strace0(c,...) \ do { \ - if ((c & _STRACE_SYSTEM) || strace.active) \ + if ((c & _STRACE_SYSTEM) || strace.active ()) \ strace.prntf (c, __PRETTY_FUNCTION__, __VA_ARGS__); \ } \ while (0) @@ -130,13 +127,13 @@ void strace_printf (unsigned, const char *func, const char *, ...); #else #define strace_printf_wrap(what, fmt, args...) \ ((void) ({\ - if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active) \ + if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active ()) \ strace.prntf(_STRACE_ ## what, __PRETTY_FUNCTION__, fmt, ## args); \ 0; \ })) #define strace_printf_wrap1(what, fmt, args...) \ ((void) ({\ - if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active) \ + if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active ()) \ strace.prntf((_STRACE_ ## what) | _STRACE_NOTALL, __PRETTY_FUNCTION__, fmt, ## args); \ 0; \ })) diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index 59a0cae..037b6c7 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -41,6 +41,8 @@ calibration_thread (VOID *arg) ExitThread (0); } +static DWORD calibration_id; + /* We need to know where the OS stores the address of the thread function on the stack so that we can intercept the call and insert some tls stuff on the stack. This function starts a known calibration thread. @@ -50,11 +52,12 @@ calibration_thread (VOID *arg) static void prime_threads () { - if (!threadfunc_ix[0]) + if (threadfunc_ix[0]) + sync_startup = INVALID_HANDLE_VALUE; + else { - DWORD id; search_for = (char *) calibration_thread; - sync_startup = CreateThread (NULL, 0, calibration_thread, 0, 0, &id); + sync_startup = CreateThread (NULL, 0, calibration_thread, 0, 0, &calibration_id); } } @@ -72,7 +75,7 @@ munge_threadfunc () for (peb = ebp, i = 0; peb < top && i < 7; peb++) if (*peb == search_for) threadfunc_ix[i++] = peb - ebp; - if (!threadfunc_ix[0]) + if (0 && !threadfunc_ix[0]) { try_to_debug (); return; @@ -82,7 +85,7 @@ munge_threadfunc () char *threadfunc = ebp[threadfunc_ix[0]]; if (threadfunc == (char *) calibration_thread) /* no need for the overhead */; - else + else if (threadfunc_ix[0]) { for (i = 0; threadfunc_ix[i]; i++) ebp[threadfunc_ix[i]] = (char *) threadfunc_fe; @@ -166,10 +169,12 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: - munge_threadfunc (); + if (!sync_startup || GetCurrentThreadId () == calibration_id) + munge_threadfunc (); break; case DLL_THREAD_DETACH: - _my_tls.remove (0); + if (!sync_startup) + _my_tls.remove (0); break; } diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 3676a3a..90689ff 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -258,7 +258,7 @@ malloc_init () calls to malloc/free/realloc to application provided. This may happen if some other dll calls cygwin's malloc, but main code provides its own malloc */ - if (!user_data->forkee) + if (!in_forkee) { user_data->free (user_data->malloc (16)); if (export_malloc_called) diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 7940051..84d326b 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -54,10 +54,7 @@ set_myself (HANDLE h) myself->dwProcessId = GetCurrentProcessId (); GetModuleFileName (NULL, myself->progname, sizeof (myself->progname)); -#ifndef DEBUGGING - if (!strace.active) -#endif - strace.hello (); + strace.hello (); debug_printf ("myself->dwProcessId %u", myself->dwProcessId); if (h) { diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 49b5eec..e5e068d 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -768,7 +768,7 @@ child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subpr sigproc_printf ("subproc_ready %p", subproc_ready); cygheap = ::cygheap; cygheap_max = ::cygheap_max; - dwProcessId = myself->dwProcessId; + straced = strace.attached (); /* Create an inheritable handle to pass to the child process. This will allow the child to duplicate handles from the parent to itself. */ parent = NULL; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 3b798ff..23b0ca5 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -424,7 +424,7 @@ spawn_guts (const char * prog_arg, const char *const *argv, pthread_cleanup_push (do_cleanup, (void *) &cleanup); av newargv; linebuf one_line; - child_info_spawn ciresrv; + child_info_spawn ch; path_conv real_path; bool reset_sendsig = false; @@ -643,11 +643,11 @@ spawn_guts (const char * prog_arg, const char *const *argv, res = -1; goto out; } - ciresrv.set (chtype, real_path.iscygexec ()); - ciresrv.moreinfo = moreinfo; + ch.set (chtype, real_path.iscygexec ()); + ch.moreinfo = moreinfo; - si.lpReserved2 = (LPBYTE) &ciresrv; - si.cbReserved2 = sizeof (ciresrv); + si.lpReserved2 = (LPBYTE) &ch; + si.cbReserved2 = sizeof (ch); /* When ruid != euid we create the new process under the current original account and impersonate in child, this way maintaining the different @@ -731,6 +731,9 @@ spawn_guts (const char * prog_arg, const char *const *argv, goto out; } + if (!(flags & CREATE_SUSPENDED)) + strace.write_childpid (ch, pi.dwProcessId); + /* Fixup the parent data structures if needed and resume the child's main thread. */ if (cygheap->fdtab.need_fixup_before ()) @@ -818,12 +821,15 @@ spawn_guts (const char * prog_arg, const char *const *argv, /* Start the child running */ if (flags & CREATE_SUSPENDED) - ResumeThread (pi.hThread); + { + ResumeThread (pi.hThread); + strace.write_childpid (ch, pi.dwProcessId); + } ForceCloseHandle (pi.hThread); sigproc_printf ("spawned windows pid %d", pi.dwProcessId); - synced = ciresrv.sync (pid, pi.hProcess, INFINITE); + synced = ch.sync (pid, pi.hProcess, INFINITE); switch (mode) { diff --git a/winsup/cygwin/strace.cc b/winsup/cygwin/strace.cc index 6634a68..9e59296 100644 --- a/winsup/cygwin/strace.cc +++ b/winsup/cygwin/strace.cc @@ -25,6 +25,7 @@ details. */ #include "fhandler.h" #include "dtable.h" #include "cygheap.h" +#include "child_info.h" #define PROTECT(x) x[sizeof (x)-1] = 0 #define CHECK(x) if (x[sizeof (x)-1] != 0) { small_printf ("array bound exceeded %d\n", __LINE__); ExitProcess (1); } @@ -36,27 +37,25 @@ class strace NO_COPY strace; void strace::hello () { - char buf[30]; - - if (inited) - { - active ^= 1; - return; - } - - inited = 1; - if (!being_debugged ()) + if (_active || !being_debugged ()) return; - __small_sprintf (buf, "cYg%8x %x", _STRACE_INTERFACE_ACTIVATE_ADDR, &active); + char buf[30]; + __small_sprintf (buf, "cYg%8x %x", _STRACE_INTERFACE_ACTIVATE_ADDR, &_active); OutputDebugString (buf); - if (active) + if (active ()) { + char pidbuf[40]; + if (myself->progname[0]) + __small_sprintf (pidbuf, "(pid %d, ppid %d)", myself->pid, myself->ppid ?: 1); + else + { + GetModuleFileName (NULL, myself->progname, sizeof (myself->progname)); + __small_sprintf (pidbuf, "(windows pid %d)", GetCurrentProcessId ()); + } prntf (1, NULL, "**********************************************"); - prntf (1, NULL, "Program name: %s (pid %d, ppid %d)", myself->progname, - myself->pid ?: GetCurrentProcessId (), - myself->ppid ?: 1); + prntf (1, NULL, "Program name: %s %s", myself->progname, pidbuf); prntf (1, NULL, "App version: %d.%d, api: %d.%d", user_data->dll_major, user_data->dll_minor, user_data->api_major, user_data->api_minor); @@ -65,7 +64,8 @@ strace::hello () cygwin_version.api_major, cygwin_version.api_minor); prntf (1, NULL, "DLL build: %s", cygwin_version.dll_build_date); prntf (1, NULL, "OS version: Windows %s", wincap.osname ()); - prntf (1, NULL, "Heap size: %u", cygheap->user_heap.chunk); + if (cygheap) + prntf (1, NULL, "Heap size: %u", cygheap->user_heap.chunk); prntf (1, NULL, "**********************************************"); } } @@ -111,6 +111,16 @@ getfunc (char *in_dst, const char *func) return dst - in_dst; } +static char * +mypid (char *buf) +{ + if (myself && myself->pid) + __small_sprintf (buf, "%d", myself->pid); + else + __small_sprintf (buf, "(%d)", cygwin_pid (GetCurrentProcessId ())); + return buf; +} + extern "C" char *__progname; /* sprintf analog for use by output routines. */ @@ -122,12 +132,11 @@ strace::vsprntf (char *buf, const char *func, const char *infmt, va_list ap) static NO_COPY bool nonewline = false; DWORD err = GetLastError (); const char *tn = cygthread::name (); - char *pn = __progname ?: (myself ? myself->progname : NULL); int microsec = microseconds (); lmicrosec = microsec; - __small_sprintf (fmt, "%7d [%s] %s ", microsec, tn, "%s %d%s"); + __small_sprintf (fmt, "%7d [%s] %s ", microsec, tn, "%s %s%s"); SetLastError (err); @@ -135,21 +144,33 @@ strace::vsprntf (char *buf, const char *func, const char *infmt, va_list ap) count = 0; else { - char *p, progname[CYG_MAX_PATH]; + char *pn; + if (!cygwin_finished_initializing) + pn = myself ? myself->progname : NULL; + else if (__progname) + pn = __progname; + else + pn = NULL; + + char *p; + char progname[CYG_MAX_PATH]; if (!pn) - p = (char *) "*** unknown ***"; + GetModuleFileName (NULL, pn = progname, sizeof (progname)); + if (!pn) + /* hmm */; else if ((p = strrchr (pn, '\\')) != NULL) p++; else if ((p = strrchr (pn, '/')) != NULL) p++; else p = pn; - strcpy (progname, p); + if (p != progname) + strcpy (progname, p); if ((p = strrchr (progname, '.')) != NULL && strcasematch (p, ".exe")) *p = '\000'; p = progname; - count = __small_sprintf (buf, fmt, p && *p ? p : "?", - (myself && myself->pid) ? myself->pid : GetCurrentProcessId (), + char tmpbuf[20]; + count = __small_sprintf (buf, fmt, p && *p ? p : "?", mypid (tmpbuf), execing ? "!" : ""); if (func) count += getfunc (buf + count, func); @@ -195,6 +216,20 @@ strace::write (unsigned category, const char *buf, int count) #undef PREFIX } +void +strace::write_childpid (child_info& ch, DWORD pid) +{ + char buf[30]; + + if (!attached () || !being_debugged ()) + return; +int res = + WaitForSingleObject (ch.subproc_ready, 30000); +do { if ((0x00040 & 0x08000) || active ()) prntf (0x00040, __PRETTY_FUNCTION__, "res %d", res); } while (0); + __small_sprintf (buf, "cYg%8x %x", _STRACE_CHILD_PID, pid); + OutputDebugString (buf); +} + /* Printf function used when tracing system calls. Warning: DO NOT SET ERRNO HERE! */ @@ -229,7 +264,7 @@ strace::vprntf (unsigned category, const char *func, const char *fmt, va_list ap } #ifndef NOSTRACE - if (active) + if (active ()) write (category, buf, len); #endif SetLastError (err); @@ -249,7 +284,7 @@ strace_printf (unsigned category, const char *func, const char *fmt, ...) { va_list ap; - if ((category & _STRACE_SYSTEM) || strace.active) + if ((category & _STRACE_SYSTEM) || strace.active ()) { va_start (ap, fmt); strace.vprntf (category, func, fmt, ap); @@ -417,7 +452,7 @@ ta[] = void strace::wm (int message, int word, int lon) { - if (active) + if (active ()) { int i; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 2e40ade..55031f9 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -344,6 +344,7 @@ extern SYSTEM_INFO system_info; /* The title on program start. */ extern char *old_title; extern bool display_title; +extern bool in_forkee; extern HANDLE hMainThread; extern HANDLE hMainProc; diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index 33e193d..417d5a7 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,5 +1,25 @@ 2005-12-29 Christopher Faylor <cgf@timesys.com> + * 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'. + +2005-12-29 Christopher Faylor <cgf@timesys.com> + * cygcheck.cc (common_apps): Add crontab, vi, vim. 2005-12-19 Igor Pechtchanski <pechtcha@cs.nyu.edu> diff --git a/winsup/utils/strace.cc b/winsup/utils/strace.cc index 3a34b31..5347b7a 100644 --- a/winsup/utils/strace.cc +++ b/winsup/utils/strace.cc @@ -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; diff --git a/winsup/utils/utils.sgml b/winsup/utils/utils.sgml index 5abdda7..aad1869 100644 --- a/winsup/utils/utils.sgml +++ b/winsup/utils/utils.sgml @@ -1489,6 +1489,8 @@ Trace system calls and signals numbers for Windows errors -o, --output=FILENAME set output file to FILENAME -p, --pid=n attach to executing program with cygwin pid n + -q, --quiet toggle "quiet" flag. Defaults to on if "-p", + off otherwise. -S, --flush-period=PERIOD flush buffered strace output every PERIOD secs -t, --timestamp use an absolute hh:mm:ss timestamp insted of the default microsecond timestamp. Implies -d |