Devel-CoreDump
view release on metacpan or search on metacpan
src/elfcore.c view on Meta::CPAN
memset(&prstatus, 0, sizeof(struct prstatus));
prstatus.pr_pid = prpsinfo.pr_pid;
prstatus.pr_ppid = prpsinfo.pr_ppid;
prstatus.pr_pgrp = prpsinfo.pr_pgrp;
prstatus.pr_sid = prpsinfo.pr_sid;
prstatus.pr_fpvalid = 1;
NO_INTR(stat_fd = sys_open("/proc/self/stat", O_RDONLY, 0));
if (stat_fd >= 0) {
char scratch[4096];
ssize_t size = c_read(stat_fd, scratch, sizeof(scratch) - 1, &errno);
if (size >= 0) {
unsigned long tms;
char *ptr = scratch;
scratch[size] = '\000';
/* User time */
for (i = 13; i && *ptr; ptr++) if (*ptr == ' ') i--;
tms = 0;
while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';
prstatus.pr_utime.tv_sec = tms / 1000;
prstatus.pr_utime.tv_usec = (tms % 1000) * 1000;
/* System time */
if (*ptr) ptr++;
tms = 0;
while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';
prstatus.pr_stime.tv_sec = tms / 1000;
prstatus.pr_stime.tv_usec = (tms % 1000) * 1000;
/* Cumulative user time */
if (*ptr) ptr++;
tms = 0;
while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';
prstatus.pr_cutime.tv_sec = tms / 1000;
prstatus.pr_cutime.tv_usec = (tms % 1000) * 1000;
/* Cumulative system time */
if (*ptr) ptr++;
tms = 0;
while (*ptr && *ptr != ' ') tms = 10*tms + *ptr++ - '0';
prstatus.pr_cstime.tv_sec = tms / 1000;
prstatus.pr_cstime.tv_usec = (tms % 1000) * 1000;
/* Pending signals */
for (i = 14; i && *ptr; ptr++) if (*ptr == ' ') i--;
while (*ptr && *ptr != ' ')
prstatus.pr_sigpend = 10*prstatus.pr_sigpend + *ptr++ - '0';
/* Held signals */
if (*ptr) ptr++;
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 =
GetCoreDumpParameter(params, compressors);
const struct CoredumperCompressor **selected_compressor =
(const struct CoredumperCompressor **)GetCoreDumpParameter(
params, selected_compressor);
int prioritize =
GetCoreDumpParameter(params, flags) & COREDUMPER_FLAG_LIMITED_BY_PRIORITY;
const struct CoredumperNote *notes =
GetCoreDumpParameter(params, notes);
int note_count =
GetCoreDumpParameter(params, note_count);
if (selected_compressor != NULL) {
/* For now, assume that the core dump is uncompressed; we will later
* override this setting, if we can find a suitable compressor program.
*/
*selected_compressor = compressors;
while (*selected_compressor &&
(*selected_compressor)->compressor != NULL) {
++*selected_compressor;
}
}
if (file_name == NULL) {
/* Create a file descriptor that can be used for reading data from
* our child process. This is a little complicated because we need
* to make sure there is no race condition with other threads
* calling fork() at the same time (this is somewhat mitigated,
* because our threads are supposedly suspended at this time). We
* have to avoid other processes holding our file handles open. We
* can do this by creating the pipe in the child and passing the
* file handle back to the parent.
*/
if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0) {
/* 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.
*/
if (CreatePipeline(fds, openmax, PATH, &compressors) < 0 ||
(fds[0] < 0 && sys_pipe(fds) < 0)) {
sys__exit(1);
}
/* Pass file handle to parent */
/* scope */ {
char cmsg_buf[CMSG_SPACE(sizeof(int))];
struct kernel_iovec iov;
struct kernel_msghdr msg;
struct cmsghdr *cmsg;
memset(&iov, 0, sizeof(iov));
memset(&msg, 0, sizeof(msg));
iov.iov_base = (void *)&compressors;
iov.iov_len = sizeof(compressors);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &cmsg_buf;
msg.msg_controllen = sizeof(cmsg_buf);
cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg) {
/* This can't happen, but static analyzers still complain... */
sys__exit(1);
}
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*(int *)CMSG_DATA(cmsg) = fds[0];
while (sys_sendmsg(pair[1], &msg, 0) < 0) {
if (errno != EINTR)
sys__exit(1);
}
while (sys_shutdown(pair[1], SHUT_RDWR) < 0) {
if (errno != EINTR)
sys__exit(1);
}
}
/* Close all file handles other than the write end of our pipe */
for (i = 0; i < openmax; i++) {
if (i != fds[1]) {
NO_INTR(sys_close(i)); }
}
/* If compiled without threading support, this is the only
* place where we can request the parent's CPU
* registers. This function is a no-op when threading
* support is available.
*/
( run in 0.666 second using v1.01-cache-2.11-cpan-39bf76dae61 )