Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2005-12-29 23:46:34 +0300
committerChristopher Faylor <me@cgf.cx>2005-12-29 23:46:34 +0300
commit5d97040501505d37b01268fdf335ef6ea2bafb44 (patch)
tree2764464e535cc8ec94122a853743e5583f2b0c95
parent10e4168d8441980eeec3a5d3ce7f5a6052c3ee27 (diff)
*** 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/ChangeLog70
-rw-r--r--winsup/cygwin/child_info.h5
-rw-r--r--winsup/cygwin/cygtls.cc2
-rw-r--r--winsup/cygwin/dcrt0.cc64
-rw-r--r--winsup/cygwin/dll_init.cc4
-rw-r--r--winsup/cygwin/external.cc2
-rw-r--r--winsup/cygwin/fhandler.cc2
-rw-r--r--winsup/cygwin/fhandler_tty.cc2
-rw-r--r--winsup/cygwin/fork.cc6
-rw-r--r--winsup/cygwin/include/sys/strace.h31
-rw-r--r--winsup/cygwin/init.cc19
-rw-r--r--winsup/cygwin/malloc_wrapper.cc2
-rw-r--r--winsup/cygwin/pinfo.cc5
-rw-r--r--winsup/cygwin/sigproc.cc2
-rw-r--r--winsup/cygwin/spawn.cc20
-rw-r--r--winsup/cygwin/strace.cc87
-rw-r--r--winsup/cygwin/winsup.h1
-rw-r--r--winsup/utils/ChangeLog20
-rw-r--r--winsup/utils/strace.cc111
-rw-r--r--winsup/utils/utils.sgml2
20 files changed, 314 insertions, 143 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6e8d91c14..39317a2d2 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 7442e1ca4..9e6433dd5 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 03d177700..e27fe1e83 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 6e0b765b8..04bef6e56 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 b3949062c..ecfc976b1 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 b51c58b84..dc83f7b51 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 e1686e1cf..6979a5ca0 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 f7afce061..6d95ab13a 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 31a5820df..e4c3c31bb 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 e54e76ed4..9b9da1743 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 59a0cae30..037b6c795 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 3676a3a30..90689ffee 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 7940051d3..84d326b3e 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 49b5eec87..e5e068d09 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 3b798ffb8..23b0ca5d1 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 6634a68dd..9e5929632 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 2e40adeaf..55031f9b9 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 33e193d3f..417d5a7c7 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 3a34b31ba..5347b7ab5 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 5abdda782..aad186962 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