Devel-CoreDump
view release on metacpan or search on metacpan
src/elfcore.c view on Meta::CPAN
while (*ptr && *ptr != ' ')
prstatus.pr_sigpend = 10*prstatus.pr_sigpend + *ptr++ - '0';
}
NO_INTR(sys_close(stat_fd));
}
}
/* scope */ {
int openmax = sys_sysconf(_SC_OPEN_MAX);
int pagesize = sys_sysconf(_SC_PAGESIZE);
struct kernel_sigset_t old_signals, blocked_signals;
const struct CoreDumpParameters *params =
va_arg(ap, const struct CoreDumpParameters *);
const char *file_name =
va_arg(ap, const char *);
size_t max_length =
GetCoreDumpParameter(params, max_length);
const char *PATH =
va_arg(ap, const char *);
const struct CoredumperCompressor *compressors =
src/elfcore.c view on Meta::CPAN
/* Block signals prior to forking. Technically, POSIX requires
* us to call pthread_sigmask(), if this is a threaded
* application. When using glibc, we are OK calling
* sigprocmask(), though. We will end up blocking additional
* signals that libpthread uses internally, but that
* is actually exactly what we want.
*
* Also, POSIX claims that this should not actually be
* necessarily, but reality says otherwise.
*/
sys_sigfillset(&blocked_signals);
sys_sigprocmask(SIG_BLOCK, &blocked_signals, &old_signals);
/* Create a new core dump in child process; call sys_fork() in order to
* avoid complications with pthread_atfork() handlers. In the child
* process, we should only ever call system calls.
*/
if ((rc = sys_fork()) == 0) {
int fds[2];
/* Create a pipe for communicating between processes. If
* necessary, add a compressor to the pipeline.
src/linuxthreads.c view on Meta::CPAN
#include <linux/dirent.h>
#include "linux_syscall_support.h"
#include "thread_lister.h"
#ifndef CLONE_UNTRACED
#define CLONE_UNTRACED 0x00800000
#endif
/* Synchronous signals that should not be blocked while in the lister thread.
*/
static const int sync_signals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS,
SIGXCPU, SIGXFSZ };
/* itoa() is not a standard function, and we cannot safely call printf()
* after suspending threads. So, we just implement our own copy. A
* recursive approach is the easiest here.
*/
static char *local_itoa(char *buf, int i) {
if (i < 0) {
src/linuxthreads.c view on Meta::CPAN
/* This function gets the list of all linux threads of the current process
* passes them to the 'callback' along with the 'parameter' pointer; at the
* call back call time all the threads are paused via
* PTRACE_ATTACH.
* The callback is executed from a separate thread which shares only the
* address space, the filesystem, and the filehandles with the caller. Most
* notably, it does not share the same pid and ppid; and if it terminates,
* the rest of the application is still there. 'callback' is supposed to do
* or arrange for ResumeAllProcessThreads. This happens automatically, if
* the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous
* signals are blocked. If the 'callback' decides to unblock them, it must
* ensure that they cannot terminate the application, or that
* ResumeAllProcessThreads will get called.
* It is an error for the 'callback' to make any library calls that could
* acquire locks. Most notably, this means that most system calls have to
* avoid going through libc. Also, this means that it is not legal to call
* exit() or abort().
* We return -1 on error and the return value of 'callback' on success.
*/
int ListAllProcessThreads(void *parameter,
ListAllProcessThreadsCallBack callback, ...) {
char altstack_mem[ALT_STACKSIZE];
struct ListerParams args;
pid_t clone_pid;
int dumpable = 1, sig;
struct kernel_sigset_t sig_blocked, sig_old;
va_start(args.ap, callback);
/* If we are short on virtual memory, initializing the alternate stack
* might trigger a SIGSEGV. Let's do this early, before it could get us
* into more trouble (i.e. before signal handlers try to use the alternate
* stack, and before we attach to other threads).
*/
memset(altstack_mem, 0, sizeof(altstack_mem));
src/linuxthreads.c view on Meta::CPAN
/* Fill in argument block for dumper thread */
args.result = -1;
args.err = 0;
args.altstack_mem = altstack_mem;
args.parameter = parameter;
args.callback = callback;
/* Before cloning the thread lister, block all asynchronous signals, as we */
/* are not prepared to handle them. */
sys_sigfillset(&sig_blocked);
for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) {
sys_sigdelset(&sig_blocked, sync_signals[sig]);
}
if (sys_sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old)) {
args.err = errno;
args.result = -1;
goto failed;
}
/* scope */ {
/* After cloning, both the parent and the child share the same instance
* of errno. We must make sure that at least one of these processes
* (in our case, the parent) uses modified syscall macros that update
* a local copy of errno, instead.
src/thread_lister.h view on Meta::CPAN
/* This function gets the list of all linux threads of the current process
* passes them to the 'callback' along with the 'parameter' pointer; at the
* call back call time all the threads are paused via
* PTRACE_ATTACH.
* The callback is executed from a separate thread which shares only the
* address space, the filesystem, and the filehandles with the caller. Most
* notably, it does not share the same pid and ppid; and if it terminates,
* the rest of the application is still there. 'callback' is supposed to do
* or arrange for ResumeAllProcessThreads. This happens automatically, if
* the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous
* signals are blocked. If the 'callback' decides to unblock them, it must
* ensure that they cannot terminate the application, or that
* ResumeAllProcessThreads will get called.
* It is an error for the 'callback' to make any library calls that could
* acquire locks. Most notably, this means that most system calls have to
* avoid going through libc. Also, this means that it is not legal to call
* exit() or abort().
* We return -1 on error and the return value of 'callback' on success.
*/
int ListAllProcessThreads(void *parameter,
ListAllProcessThreadsCallBack callback, ...);
( run in 0.456 second using v1.01-cache-2.11-cpan-49f99fa48dc )