Merge pull request #1689 from esnet/bmah-more-json-output-fixes

More json output fixes
diff --git a/src/iperf_api.c b/src/iperf_api.c
index 139ab87..d40561c 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -2766,13 +2766,19 @@
 {
     cJSON *event = cJSON_CreateObject();
     if (!event)
-    return -1;
+        return -1;
     cJSON_AddStringToObject(event, "event", event_name);
     cJSON_AddItemReferenceToObject(event, "data", obj);
     char *str = cJSON_PrintUnformatted(event);
     if (str == NULL)
-    return -1;
+        return -1;
+    if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+        perror("iperf_json_finish: pthread_mutex_lock");
+    }
     fprintf(test->outfile, "%s\n", str);
+    if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+        perror("iperf_json_finish: pthread_mutex_unlock");
+    }
     iflush(test);
     cJSON_free(str);
     cJSON_Delete(event);
@@ -4865,49 +4871,50 @@
         if (test->server_output_text) {
             cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
         }
-        // Get ASCII rendering of JSON structure.  Then make our
-        // own copy of it and return the storage that cJSON allocated
-        // on our behalf.  We keep our own copy around.
-        char *str = cJSON_Print(test->json_top);
-        if (str == NULL) {
-            return -1;
-        }
-        test->json_output_string = strdup(str);
-        cJSON_free(str);
-        if (test->json_output_string == NULL) {
-            return -1;
-        }
 
-        if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
-            perror("iperf_json_finish: pthread_mutex_lock");
+        /* --json-stream, so we print various individual objects */
+        if (test->json_stream) {
+            cJSON *error = cJSON_GetObjectItem(test->json_top, "error");
+            if (error) {
+                JSONStream_Output(test, "error", error);
+            }
+            if (test->json_server_output) {
+                JSONStream_Output(test, "server_output_json", test->json_server_output);
+            }
+            if (test->server_output_text) {
+                JSONStream_Output(test, "server_output_text", cJSON_CreateString(test->server_output_text));
+            }
+            JSONStream_Output(test, "end", test->json_end);
         }
-        fprintf(test->outfile, "%s\n", test->json_output_string);
-        if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
-            perror("iperf_json_finish: pthread_mutex_unlock");
+        /* Original --json output, single monolithic object */
+        else {
+            /*
+             * Get ASCII rendering of JSON structure.  Then make our
+             * own copy of it and return the storage that cJSON
+             * allocated on our behalf.  We keep our own copy
+             * around.
+             */
+            char *str = cJSON_Print(test->json_top);
+            if (str == NULL) {
+                return -1;
+            }
+            test->json_output_string = strdup(str);
+            cJSON_free(str);
+            if (test->json_output_string == NULL) {
+                return -1;
+            }
+            if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+                perror("iperf_json_finish: pthread_mutex_lock");
+            }
+            fprintf(test->outfile, "%s\n", test->json_output_string);
+            if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+                perror("iperf_json_finish: pthread_mutex_unlock");
+            }
+            iflush(test);
         }
-        iflush(test);
         cJSON_Delete(test->json_top);
-        test->json_top = NULL;
     }
 
-    if (test->json_stream) {
-        cJSON *error = cJSON_GetObjectItem(test->json_top, "error");
-        if (error) {
-            JSONStream_Output(test, "error", error);
-        }
-        if (test->json_server_output) {
-            JSONStream_Output(test, "server_output_json", test->json_server_output);
-        }
-        if (test->server_output_text) {
-            JSONStream_Output(test, "server_output_text", cJSON_CreateString(test->server_output_text));
-        }
-        JSONStream_Output(test, "end", test->json_end);
-    }
-    else {
-        fprintf(test->outfile, "%s\n", test->json_output_string);
-        iflush(test);
-    }
-    cJSON_Delete(test->json_top);
     test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
     return 0;
 }
diff --git a/src/iperf_error.c b/src/iperf_error.c
index 12ab3eb..0fedf31 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -47,10 +47,6 @@
     struct tm *ltm = NULL;
     char *ct = NULL;
 
-    if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
-        perror("iperf_err: pthread_mutex_lock");
-    }
-
     /* Timestamp if requested */
     if (test != NULL && test->timestamps) {
 	time(&now);
@@ -64,6 +60,10 @@
     if (test != NULL && test->json_output && test->json_top != NULL)
 	cJSON_AddStringToObject(test->json_top, "error", str);
     else {
+        if (pthread_mutex_lock(&(test->print_mutex)) != 0) {
+            perror("iperf_err: pthread_mutex_lock");
+        }
+
 	if (test && test->outfile && test->outfile != stdout) {
 	    if (ct) {
 		fprintf(test->outfile, "%s", ct);
@@ -76,12 +76,13 @@
 	    }
 	    fprintf(stderr, "iperf3: %s\n", str);
 	}
+
+        if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
+            perror("iperf_err: pthread_mutex_unlock");
+        }
+
     }
     va_end(argp);
-
-    if (pthread_mutex_unlock(&(test->print_mutex)) != 0) {
-        perror("iperf_err: pthread_mutex_unlock");
-    }
 }
 
 /* Do a printf to stderr or log file as appropriate, then exit. */