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:
-rw-r--r--winsup/cygwin/environ.cc1
-rw-r--r--winsup/cygwin/exceptions.cc104
-rw-r--r--winsup/cygwin/local_includes/winsup.h1
-rw-r--r--winsup/cygwin/release/3.5.04
-rw-r--r--winsup/doc/cygwinenv.xml25
-rw-r--r--winsup/doc/new-features.xml6
-rw-r--r--winsup/doc/utils.xml43
7 files changed, 143 insertions, 41 deletions
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 008854a07..dca5c5db0 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -832,6 +832,7 @@ environ_init (char **envp, int envc)
out:
findenv_func = (char * (*)(const char*, int*)) my_findenv;
environ = envp;
+ dumper_init ();
if (envp_passed_in)
{
p = getenv ("CYGWIN");
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 642afb788..36f6a476a 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -52,6 +52,7 @@ details. */
#define DUMPSTACK_FRAME_LIMIT 32
PWCHAR debugger_command;
+PWCHAR dumper_command;
extern uint8_t _sigbe;
extern uint8_t _sigdelayed_end;
@@ -132,6 +133,42 @@ error_start_init (const char *buf)
wcscat (cp, L"\"");
}
+extern "C" void
+dumper_init (void)
+{
+ WCHAR dll_dir[PATH_MAX];
+ if (!GetModuleFileNameW (cygwin_hmodule, dll_dir, PATH_MAX))
+ return;
+
+ /* Strip off last path component ("\\cygwin1.dll") */
+ PWCHAR w = wcsrchr (dll_dir, L'\\');
+ if (!w)
+ return;
+
+ *w = L'\0';
+
+ /* Calculate the length of the command, allowing for an appended DWORD PID and
+ terminating null */
+ int cmd_len = 1 + wcslen(dll_dir) + 11 + 2 + 1 + wcslen(global_progname) + 1 + 10 + 1;
+ if (cmd_len > 32767)
+ {
+ /* If this comes to more than the 32,767 characters CreateProcess() can
+ accept, we can't work, so don't set dumper_command */
+ return;
+ }
+
+ dumper_command = (PWCHAR) malloc(cmd_len * sizeof (WCHAR));
+
+ PWCHAR cp = dumper_command;
+ cp = wcpcpy (cp, L"\"");
+ cp = wcpcpy (cp, dll_dir);
+ cp = wcpcpy (cp, L"\\dumper.exe");
+ cp = wcpcpy (cp, L"\" ");
+ cp = wcpcpy (cp, L"\"");
+ cp = wcpcpy (cp, global_progname);
+ wcscat (cp, L"\"");
+}
+
void
cygwin_exception::open_stackdumpfile ()
{
@@ -454,20 +491,14 @@ cygwin_stackdump ()
exc.dumpstack ();
}
-extern "C" int
-try_to_debug ()
+static
+int exec_prepared_command (PWCHAR command)
{
- if (!debugger_command)
+ if (!command)
return 0;
- debug_printf ("debugger_command '%W'", debugger_command);
- if (being_debugged ())
- {
- extern void break_here ();
- break_here ();
- return 0;
- }
+ debug_printf ("executing prepared command '%W'", command);
- PWCHAR dbg_end = wcschr (debugger_command, L'\0');
+ PWCHAR dbg_end = wcschr (command, L'\0');
__small_swprintf (dbg_end, L" %u", GetCurrentProcessId ());
LONG prio = GetThreadPriority (GetCurrentThread ());
@@ -509,11 +540,12 @@ try_to_debug ()
}
FreeEnvironmentStringsW (rawenv);
- console_printf ("*** starting debugger for pid %u, tid %u\n",
+ console_printf ("*** starting '%W' for pid %u, tid %u\r\n",
+ command,
cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
BOOL dbg;
dbg = CreateProcessW (NULL,
- debugger_command,
+ command,
NULL,
NULL,
FALSE,
@@ -527,11 +559,15 @@ try_to_debug ()
we can't wait here for the error_start process to exit, as if it's a
debugger, it might want to continue this thread. So we busy wait until a
debugger attaches, which stops this process, after which it can decide if
- we continue or not. */
+ we continue or not.
+
+ Note that this is still racy: if the error_start process does it's work too
+ fast, we don't notice that it attached and get stuck here.
+ */
*dbg_end = L'\0';
if (!dbg)
- system_printf ("Failed to start debugger, %E");
+ system_printf ("Failed to start, %E");
else
{
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
@@ -540,13 +576,29 @@ try_to_debug ()
Sleep (2000);
}
- console_printf ("*** continuing pid %u from debugger call (%d)\n",
- cygwin_pid (GetCurrentProcessId ()), dbg);
+ console_printf ("*** continuing pid %u\r\n",
+ cygwin_pid (GetCurrentProcessId ()));
SetThreadPriority (GetCurrentThread (), prio);
return dbg;
}
+extern "C" int
+try_to_debug ()
+{
+ /* If already being debugged, break into the debugger (Note that this function
+ can be called from places other than an exception) */
+ if (being_debugged ())
+ {
+ extern void break_here ();
+ break_here ();
+ return 1;
+ }
+
+ /* Otherwise, invoke the JIT debugger, if set */
+ return exec_prepared_command (debugger_command);
+}
+
/* myfault exception handler. */
EXCEPTION_DISPOSITION
exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
@@ -1264,7 +1316,6 @@ signal_exit (int sig, siginfo_t *si, void *)
debug_printf ("exiting due to signal %d", sig);
exit_state = ES_SIGNAL_EXIT;
- if (cygheap->rlim_core > 0UL)
switch (sig)
{
case SIGABRT:
@@ -1277,9 +1328,24 @@ signal_exit (int sig, siginfo_t *si, void *)
case SIGTRAP:
case SIGXCPU:
case SIGXFSZ:
- sig |= 0x80; /* Flag that we've "dumped core" */
if (try_to_debug ())
break;
+
+ if (cygheap->rlim_core == 0Ul)
+ break;
+
+ sig |= 0x80; /* Set flag in exit status to show that we've "dumped core" */
+
+ /* If core dump size is >1MB, try to invoke dumper to write a
+ .core file */
+ if (cygheap->rlim_core > 1024*1024)
+ {
+ if (exec_prepared_command (dumper_command))
+ break;
+ /* If that failed, fall-through to... */
+ }
+
+ /* Otherwise write a .stackdump */
if (si->si_code != SI_USER && si->si_cyg)
{
cygwin_exception *exc = (cygwin_exception *) si->si_cyg;
diff --git a/winsup/cygwin/local_includes/winsup.h b/winsup/cygwin/local_includes/winsup.h
index bf0a0bcc3..76957618b 100644
--- a/winsup/cygwin/local_includes/winsup.h
+++ b/winsup/cygwin/local_includes/winsup.h
@@ -179,6 +179,7 @@ void close_all_files (bool = false);
/* debug_on_trap support. see exceptions.cc:try_to_debug() */
extern "C" void error_start_init (const char*);
+extern "C" void dumper_init (void);
extern "C" int try_to_debug ();
void ld_preload ();
diff --git a/winsup/cygwin/release/3.5.0 b/winsup/cygwin/release/3.5.0
index 6209064a6..1e62316a0 100644
--- a/winsup/cygwin/release/3.5.0
+++ b/winsup/cygwin/release/3.5.0
@@ -60,3 +60,7 @@ What changed:
- Enable automatic sparsifying of files on SSDs, independent of the
"sparse" mount mode.
+
+- When RLIMIT_CORE is more than 1MB, a core dump file which can be loaded by gdb
+ is now written on a fatal error. Otherwise, if it's greater than zero, a text
+ format .stackdump file is written, as previously.
diff --git a/winsup/doc/cygwinenv.xml b/winsup/doc/cygwinenv.xml
index 5e17404a7..d97f2b77d 100644
--- a/winsup/doc/cygwinenv.xml
+++ b/winsup/doc/cygwinenv.xml
@@ -23,18 +23,29 @@ Defaults to off.</para>
<listitem>
<para>
-<envar>error_start:Win32filepath</envar> - if set, runs
-<filename>Win32filepath</filename> when cygwin encounters a fatal error,
-which is useful for debugging. <filename>Win32filepath</filename> is
-usually set to the path to <command>gdb</command> or
-<command>dumper</command>, for example
-<filename>C:\cygwin\bin\gdb.exe</filename>.
-There is no default set.
+<envar>error_start:Win32filepath</envar> - if set, runs
+<filename>Win32filepath</filename> when cygwin encounters a fatal error, which
+can be useful for debugging. Defaults to not set.
+</para>
+<para>
+<filename>Win32filepath</filename> is typically set to <command>gdb</command> or
+<command>dumper</command>. If giving a path in
+<filename>Win32filepath</filename>, note that it is a Windows-style path and not
+a Cygwin path.
</para>
<para>
The filename of the executing program and it's Windows process id are appended
to the command as arguments.
</para>
+<para>
+ Note: This takes priority over writing core dump or .stackdump files, if
+ enabled by <function>setrlimit(RLIMIT_CORE)</function> (e.g. via
+ <command>ulimit -c</command>).
+</para>
+<para>
+ Note: This has no effect if a debugger is already attached when the fatal
+ error occurs.
+</para>
</listitem>
<listitem>
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 0abe1c41c..f8e38f5c4 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -97,6 +97,12 @@ Enable automatic sparsifying of files on SSDs, independent of the
"sparse" mount mode.
</para></listitem>
+<listitem><para>
+When RLIMIT_CORE is more than 1MB, a core dump file which can be loaded by gdb
+is now written on a fatal error. Otherwise, if it's greater than zero, a text
+format .stackdump file is written, as previously.
+</para></listitem>
+
</itemizedlist>
</sect2>
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 9210c94e2..692dae38f 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -721,17 +721,17 @@ explorer $XPATH &
<refsect1 id="dumper-desc">
<title>Description</title>
<para>The <command>dumper</command> utility can be used to create a core
- dump of running Windows process. This core dump can be later loaded to
- <command>gdb</command> and analyzed. One common way to use
- <command>dumper</command> is to plug it into cygwin's Just-In-Time
- debugging facility by adding
- <screen>
-error_start=x:\path\to\dumper.exe
-</screen> to the
- <emphasis>CYGWIN</emphasis> environment variable. Please note that
- <literal>x:\path\to\dumper.exe</literal> is Windows-style and not cygwin
- path. If <literal>error_start</literal> is set this way, then dumper will
- be started whenever some program encounters a fatal error. </para>
+ dump of running Windows process. This core dump can be later loaded into
+ <command>gdb</command> and analyzed.
+ </para>
+
+ <para>
+ If the core file size limit is set to unlimited (e.g. <command>ulimit -c
+ unlimited</command>) and an <literal>error_start</literal> executable
+ hasn't been configured in the <literal>CYGWIN</literal> environment
+ variable, Cygwin will automatically run <command>dumper</command> when a
+ fatal error occurs.
+ </para>
<para> <command>dumper</command> can be also be started from the command
line to create a core dump of any running process.</para>
@@ -742,14 +742,25 @@ error_start=x:\path\to\dumper.exe
terminated.</para>
<para> To save space in the core dump, <command>dumper</command> doesn't
- write those portions of the target process's memory space that are loaded
+ write those portions of the target process's memory space that were loaded
from executable and dll files and are unchanged (e.g. program code).
Instead, <command>dumper</command> saves paths to the files which
contain that data. When a core dump is loaded into gdb, it uses these
paths to load the appropriate files. That means that if you create a core
dump on one machine and try to debug it on another, you'll need to place
identical copies of the executable and dlls in the same directories as on
- the machine where the core dump was created. </para>
+ the machine where the core dump was created.
+ </para>
+ </refsect1>
+
+ <refsect1 id="dumper-notes">
+ <title>Notes</title>
+ <para>
+ A Cygwin "core dump file" is an ELF file containing the mutable parts of
+ the process memory and special note sections which capture the process,
+ thread and loaded module context needed to recreate the process image in a
+ debugger.
+ </para>
</refsect1>
</refentry>
@@ -1497,8 +1508,10 @@ bash$ locale noexpr
<para>
<command>minidumper</command> can be used with cygwin's Just-In-Time
- debugging facility in exactly the same way as <command>dumper</command>
- (See <xref linkend="dumper"></xref>).
+ debugging facility by adding <code>error_start=minidumper</code> to the
+ <literal>CYGWIN</literal> environment variable. If <literal>CYGWIN</literal>
+ is set this way, then <command>minidumper</command> will be started whenever
+ a program encounters a fatal exception.
</para>
<para>