changeset 13987:c8aa73ad0c0b

3567 dtrace print() doesn't play well with ::dtrace Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Gordon Ross <gwr@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Dan Kimmel <dan.kimmel@delphix.com>
date Thu, 14 Mar 2013 21:56:45 -0800
parents 341879d91372
children 81670e8b6dd9
files usr/src/cmd/mdb/common/modules/dtrace/dtrace.c
diffstat 1 files changed, 45 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c	Thu Mar 14 18:08:41 2013 -0400
+++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c	Thu Mar 14 21:56:45 2013 -0800
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 /*
@@ -43,6 +44,8 @@
 #include <ctype.h>
 #include <errno.h>
 #include <math.h>
+#include <stdio.h>
+#include <unistd.h>
 
 /*ARGSUSED*/
 int
@@ -871,8 +874,41 @@
 	int dtdd_quiet;
 	int dtdd_flowindent;
 	int dtdd_heading;
+	FILE *dtdd_output;
 } dtrace_dcmddata_t;
 
+/*
+ * Helper to grab all the content from a file, spit it into a string, and erase
+ * and reset the file.
+ */
+static void
+print_and_truncate_file(FILE *fp)
+{
+	long len;
+	char *out;
+
+	/* flush, find length of file, seek to beginning, initialize buffer */
+	if (fflush(fp) || (len = ftell(fp)) < 0 ||
+	    fseek(fp, 0, SEEK_SET) < 0) {
+		mdb_warn("couldn't prepare DTrace output file: %d\n", errno);
+		return;
+	}
+
+	out = mdb_alloc(len + 1, UM_SLEEP);
+	out[len] = '\0';
+
+	/* read file into buffer, truncate file, and seek to beginning */
+	if ((fread(out, len + 1, sizeof (char), fp) == 0 && ferror(fp)) ||
+	    ftruncate(fileno(fp), 0) < 0 || fseek(fp, 0, SEEK_SET) < 0) {
+		mdb_warn("couldn't read DTrace output file: %d\n", errno);
+		mdb_free(out, len + 1);
+		return;
+	}
+
+	mdb_printf("%s", out);
+	mdb_free(out, len + 1);
+}
+
 /*ARGSUSED*/
 static int
 dtrace_dcmdrec(const dtrace_probedata_t *data,
@@ -880,6 +916,8 @@
 {
 	dtrace_dcmddata_t *dd = arg;
 
+	print_and_truncate_file(dd->dtdd_output);
+
 	if (rec == NULL) {
 		/*
 		 * We have processed the final record; output the newline if
@@ -1083,7 +1121,12 @@
 		goto err;
 	}
 
-	if (dtrace_consume(dtp, NULL,
+	if ((dd.dtdd_output = tmpfile()) == NULL) {
+		mdb_warn("couldn't open DTrace output file: %d\n", errno);
+		goto err;
+	}
+
+	if (dtrace_consume(dtp, dd.dtdd_output,
 	    dtrace_dcmdprobe, dtrace_dcmdrec, &dd) == -1) {
 		mdb_warn("couldn't consume DTrace buffers: %s\n",
 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
@@ -1098,6 +1141,7 @@
 	rval = DCMD_OK;
 err:
 	dtrace_close(dtp);
+	fclose(dd.dtdd_output);
 	return (rval);
 }