[DTrace-devel] [PATCH] The printf action without conversions was not getting printed

Kris Van Hees kris.van.hees at oracle.com
Thu Jun 18 18:51:46 PDT 2020


Eugene Loh reported an issue with the printf action:

> Consider
>
>          # dtrace -n 'BEGIN
>          {
>              printf("Hello world.\n");
>              printf("Hello world. %d\n", 0);
>              exit(0);
>          }'
>
> The first printf() is not printed.  The second one is.
>
> I think the problem is that user space prints output based on
> "records" that are formed during BPF code generation, but the
> first printf() doesn't need any BPF code and therefore has no
> "record."

Indeed, no record descriptor was being generated for the case where
a constant format string is provided without conversions.  That
means that when the buffer is being consumed there is nothing to
indicate that output should be provided.

If printf() does not have arguments beyond the format string, we
add a record descriptor without data (kind = DTRACEACT_PRINTF,
size = 0, alignment = 1).  This ensures that when this record
descriptor is encountered in the metadata, the constant format
string will be printed.

Four tests are added to exercise this feature.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                             | 18 +++++++++++----
 .../actions/printf/tst.no-conv.first.d        | 22 ++++++++++++++++++
 .../actions/printf/tst.no-conv.first.r        |  1 +
 .../actions/printf/tst.no-conv.last.d         | 22 ++++++++++++++++++
 .../actions/printf/tst.no-conv.last.r         |  1 +
 .../actions/printf/tst.no-conv.middle.d       | 23 +++++++++++++++++++
 .../actions/printf/tst.no-conv.middle.r       |  1 +
 .../actions/printf/tst.no-conv.only.d         | 21 +++++++++++++++++
 .../actions/printf/tst.no-conv.only.r         |  1 +
 9 files changed, 105 insertions(+), 5 deletions(-)
 create mode 100644 test/unittest/actions/printf/tst.no-conv.first.d
 create mode 100644 test/unittest/actions/printf/tst.no-conv.first.r
 create mode 100644 test/unittest/actions/printf/tst.no-conv.last.d
 create mode 100644 test/unittest/actions/printf/tst.no-conv.last.r
 create mode 100644 test/unittest/actions/printf/tst.no-conv.middle.d
 create mode 100644 test/unittest/actions/printf/tst.no-conv.middle.r
 create mode 100644 test/unittest/actions/printf/tst.no-conv.only.d
 create mode 100644 test/unittest/actions/printf/tst.no-conv.only.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index dc1e52b3..d9f5733b 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -577,12 +577,20 @@ dt_cg_act_printf(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 			   DTRACEACT_AGGREGATION, arg1);
 
 	/*
-	 * Generate code to store the arguments.  If no arguments are provided,
-	 * we are printing a string constant, and no data needs to be written
-	 * to the output buffer.
+	 * If no arguments are provided we will be printing a string constant.
+	 * We do not write any data to the output buffer but we do need to add
+	 * a record descriptor to indicate that at this point in the output
+	 * stream, a string must be printed.
+	 *
+	 * If there are arguments, we need to generate code to store their
+	 * values.
 	 */
-	for (anp = arg1; anp != NULL; anp = anp->dn_list)
-		dt_cg_store_val(pcb, anp, kind, pfp, 0);
+	if (arg1 == NULL)
+		dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, kind, 0, 1, pfp, 0);
+	else {
+		for (anp = arg1; anp != NULL; anp = anp->dn_list)
+			dt_cg_store_val(pcb, anp, kind, pfp, 0);
+	}
 }
 
 static void
diff --git a/test/unittest/actions/printf/tst.no-conv.first.d b/test/unittest/actions/printf/tst.no-conv.first.d
new file mode 100644
index 00000000..42eef721
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.first.d
@@ -0,0 +1,22 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The printf action supports a constant format string without
+ *	      conversions, when it is the first action.
+ *
+ * SECTION: Actions/printf()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf("one ");
+	trace(2);
+	exit(0);
+}
diff --git a/test/unittest/actions/printf/tst.no-conv.first.r b/test/unittest/actions/printf/tst.no-conv.first.r
new file mode 100644
index 00000000..27e0244e
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.first.r
@@ -0,0 +1 @@
+one 2
diff --git a/test/unittest/actions/printf/tst.no-conv.last.d b/test/unittest/actions/printf/tst.no-conv.last.d
new file mode 100644
index 00000000..d6ae61b6
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.last.d
@@ -0,0 +1,22 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The printf action supports a constant format string without
+ *	      conversions, when it is the last action.
+ *
+ * SECTION: Actions/printf()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace(1);
+	printf(" two");
+	exit(0);
+}
diff --git a/test/unittest/actions/printf/tst.no-conv.last.r b/test/unittest/actions/printf/tst.no-conv.last.r
new file mode 100644
index 00000000..915e89a5
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.last.r
@@ -0,0 +1 @@
+1 two
diff --git a/test/unittest/actions/printf/tst.no-conv.middle.d b/test/unittest/actions/printf/tst.no-conv.middle.d
new file mode 100644
index 00000000..8a8c12ae
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.middle.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The printf action supports a constant format string without
+ *	      conversions, when it is an action in the middle.
+ *
+ * SECTION: Actions/printf()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace(1);
+	printf(" two ");
+	trace(3);
+	exit(0);
+}
diff --git a/test/unittest/actions/printf/tst.no-conv.middle.r b/test/unittest/actions/printf/tst.no-conv.middle.r
new file mode 100644
index 00000000..39a33d5f
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.middle.r
@@ -0,0 +1 @@
+1 two 3
diff --git a/test/unittest/actions/printf/tst.no-conv.only.d b/test/unittest/actions/printf/tst.no-conv.only.d
new file mode 100644
index 00000000..1efee281
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.only.d
@@ -0,0 +1,21 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The printf action supports a constant format string without
+ *	      conversions, when it is the first only.
+ *
+ * SECTION: Actions/printf()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf("only");
+	exit(0);
+}
diff --git a/test/unittest/actions/printf/tst.no-conv.only.r b/test/unittest/actions/printf/tst.no-conv.only.r
new file mode 100644
index 00000000..6c542ab1
--- /dev/null
+++ b/test/unittest/actions/printf/tst.no-conv.only.r
@@ -0,0 +1 @@
+only
-- 
2.26.0




More information about the DTrace-devel mailing list