Fix a bug in ktruss and ktrace, where they would randomly stop tracing if

the write to the ktraced file descriptor (when they used fktrace internally)
would block. Fix by clearing the non-blocking bit in the file descriptor by
default, so that the writes will block. This has the side effect of stopping
the traced process. Add a flag to override (-n) this behavior and have the
trace stop without blocking the traced process (the previous behavior).
Fix lint, add checks to failed syscalls, ansify.
This commit is contained in:
christos 2004-06-24 15:50:50 +00:00
parent 39e498b419
commit 1e77a9474a
2 changed files with 86 additions and 43 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ktrace.1,v 1.26 2003/11/24 18:00:49 wiz Exp $
.\" $NetBSD: ktrace.1,v 1.27 2004/06/24 15:50:50 christos Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -37,7 +37,7 @@
.Nd enable kernel process tracing
.Sh SYNOPSIS
.Nm
.Op Fl aCcdis
.Op Fl aCcdins
.Op Fl f Ar trfile
.Op Fl g Ar pgrp
.Op Fl p Ar pid
@ -48,7 +48,7 @@
.Op Fl t Ar trstr
.Ar command
.Nm ktruss
.Op Fl aCcdilRT
.Op Fl aCcdilnRT
.Op Fl e Ar emulation
.Op Fl f Ar infile
.Op Fl g Ar pgrp
@ -57,7 +57,7 @@
.Op Fl p Ar pid
.Op Fl t Ar trstr
.Nm ktruss
.Op Fl adiRT
.Op Fl adinRT
.Op Fl e Ar emulation
.Op Fl m Ar maxdata
.Op Fl o Ar outfile
@ -138,10 +138,22 @@ This is used for pointer type arguments, e.g., strings.
The data will be escaped in C-style unless
.Fl x
is specified when it will be output in hex and ascii.
.It Fl n
Stop tracing if attempts to write to the trace file would block.
This option always affects
.Nm ktruss
and only affects
.Nm ktrace
when writing to
.Dv stdout .
If this flag is not set, then the traced program will block until it can
write more data to the trace file descriptor.
.It Fl o Ar outfile
Log trace records to
.Ar outfile .
Without this option ktruss will print its output in a human
Without this option
.Nm ktruss
will print its output in a human
readable format to standard out.
.It Fl p Ar pid
Enable (disable) tracing on the indicated process id (only one

View File

@ -1,4 +1,4 @@
/* $NetBSD: ktrace.c,v 1.34 2004/02/28 02:42:45 enami Exp $ */
/* $NetBSD: ktrace.c,v 1.35 2004/06/24 15:50:50 christos Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\
#if 0
static char sccsid[] = "@(#)ktrace.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: ktrace.c,v 1.34 2004/02/28 02:42:45 enami Exp $");
__RCSID("$NetBSD: ktrace.c,v 1.35 2004/06/24 15:50:50 christos Exp $");
#endif
#endif /* not lint */
@ -53,6 +53,7 @@ __RCSID("$NetBSD: ktrace.c,v 1.34 2004/02/28 02:42:45 enami Exp $");
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -65,23 +66,23 @@ __RCSID("$NetBSD: ktrace.c,v 1.34 2004/02/28 02:42:45 enami Exp $");
#include "setemul.h"
#endif
int main __P((int, char **));
int rpid __P((char *));
void usage __P((void));
int do_ktrace __P((const char *, int, int,int));
void no_ktrace __P((int));
int main(int, char **);
static int rpid(char *);
static void usage(void);
static int do_ktrace(const char *, int, int, int, int);
static void no_ktrace(int);
static void fset(int fd, int flag);
static void fclear(int fd, int flag);
#ifdef KTRUSS
extern int timestamp, decimal, fancy, tail, maxdata;
#endif
int
main(argc, argv)
int argc;
char **argv;
main(int argc, char **argv)
{
enum { NOTSET, CLEAR, CLEARALL } clear;
int append, ch, fd, trset, ops, pid, pidset, synclog, trpoints;
int block, append, ch, fd, trset, ops, pid, pidset, synclog, trpoints;
const char *outfile;
#ifdef KTRUSS
const char *infile;
@ -91,10 +92,11 @@ main(argc, argv)
clear = NOTSET;
append = ops = pidset = trset = synclog = 0;
trpoints = 0;
block = 1;
pid = 0; /* Appease GCC */
#ifdef KTRUSS
# define OPTIONS "aCce:df:g:ilm:o:p:RTt:"
# define OPTIONS "aCce:df:g:ilm:no:p:RTt:"
outfile = infile = NULL;
#else
# define OPTIONS "aCcdf:g:ip:st:"
@ -147,6 +149,9 @@ main(argc, argv)
outfile = optarg;
break;
#endif
case 'n':
block = 0;
break;
case 'p':
pid = rpid(optarg);
pidset = 1;
@ -216,7 +221,7 @@ main(argc, argv)
} else
ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE;
(void)do_ktrace(outfile, ops, trpoints, pid);
(void)do_ktrace(outfile, ops, trpoints, pid, block);
exit(0);
}
@ -230,23 +235,22 @@ main(argc, argv)
if (*argv) {
#ifdef KTRUSS
if (do_ktrace(outfile, ops, trpoints, getpid()) == 1) {
if (do_ktrace(outfile, ops, trpoints, getpid(), block) == 1) {
execvp(argv[0], &argv[0]);
err(EXIT_FAILURE, "exec of '%s' failed", argv[0]);
}
#else
(void)do_ktrace(outfile, ops, trpoints, getpid());
(void)do_ktrace(outfile, ops, trpoints, getpid(), block);
execvp(argv[0], &argv[0]);
err(EXIT_FAILURE, "exec of '%s' failed", argv[0]);
#endif
} else
(void)do_ktrace(outfile, ops, trpoints, pid);
exit(0);
(void)do_ktrace(outfile, ops, trpoints, pid, block);
return 0;
}
int
rpid(p)
char *p;
static int
rpid(char *p)
{
static int first;
@ -261,8 +265,30 @@ rpid(p)
return (atoi(p));
}
void
usage()
static void
fset(int fd, int flag)
{
int oflag = fcntl(fd, F_GETFL, 0);
if (oflag == -1)
err(EXIT_FAILURE, "Cannot get file flags");
if (fcntl(fd, F_SETFL, oflag | flag) == -1)
err(EXIT_FAILURE, "Cannot set file flags");
}
static void
fclear(int fd, int flag)
{
int oflag = fcntl(fd, F_GETFL, 0);
if (oflag == -1)
err(EXIT_FAILURE, "Cannot get file flags");
if (fcntl(fd, F_SETFL, oflag & ~flag) == -1)
err(EXIT_FAILURE, "Cannot set file flags");
}
static void
usage(void)
{
#define TRPOINTS "[Aaceilmnsuvw+-]"
@ -287,9 +313,9 @@ usage()
}
static const char *ktracefile = NULL;
void
no_ktrace(sig)
int sig;
static void
/*ARGSUSED*/
no_ktrace(int sig)
{
if (ktracefile)
@ -299,12 +325,8 @@ no_ktrace(sig)
" kernel; re-compile kernel with `options KTRACE'");
}
int
do_ktrace(tracefile, ops, trpoints, pid)
const char *tracefile;
int ops;
int trpoints;
int pid;
static int
do_ktrace(const char *tracefile, int ops, int trpoints, int pid, int block)
{
int ret;
@ -314,9 +336,9 @@ do_ktrace(tracefile, ops, trpoints, pid)
if (pipe(pi) < 0)
err(EXIT_FAILURE, "pipe(2)");
fcntl(pi[0], F_SETFD, FD_CLOEXEC | fcntl(pi[0], F_GETFD, 0));
fcntl(pi[1], F_SETFD, FD_CLOEXEC | fcntl(pi[1], F_GETFD, 0));
fset(pi[0], FD_CLOEXEC);
fset(pi[1], FD_CLOEXEC);
dofork = (pid == getpid());
#ifdef KTRUSS
@ -336,14 +358,16 @@ do_ktrace(tracefile, ops, trpoints, pid)
if (!dofork || !fpid)
#endif
{
if (!dofork)
if (!dofork) {
#ifdef KTRUSS
ret = fktrace(pi[1], ops, trpoints, fpid);
#else
ret = fktrace(pi[1], ops, trpoints, pid);
#endif
else
close(pi[1]);
if (block)
fclear(pi[1], O_NONBLOCK);
} else
(void)close(pi[1]);
#ifdef KTRUSS
dumpfile(NULL, pi[0], trpoints);
waitpid(fpid, NULL, 0);
@ -354,7 +378,10 @@ do_ktrace(tracefile, ops, trpoints, pid)
while ((n =
read(pi[0], buf, sizeof(buf))) > 0) {
write(1, buf, n);
if (write(STDOUT_FILENO, buf,
(size_t)n) == -1)
warn("write failed (%s)",
strerror(errno));
cnt += n;
}
}
@ -363,14 +390,18 @@ do_ktrace(tracefile, ops, trpoints, pid)
#endif
return 0;
}
close(pi[0]);
(void)close(pi[0]);
#ifdef KTRUSS
if (dofork && !fpid) {
ret = fktrace(pi[1], ops, trpoints, getpid());
if (block)
fclear(pi[1], O_NONBLOCK);
return 1;
}
#else
ret = fktrace(pi[1], ops, trpoints, pid);
if (block)
fclear(pi[1], O_NONBLOCK);
#endif
if (ret == -1)
err(EXIT_FAILURE, "fd %d, pid %d", pi[1], pid);