From ee4a219eecbd13d6a384542aa81a9fd01145df33 Mon Sep 17 00:00:00 2001
From: Michael Tuexen <tuexen@fh-muenster.de>
Date: Mon, 27 Aug 2018 08:16:52 +0200
Subject: [PATCH] Use appropriate error reporting for pthread_*() functions.

---
 gtests/net/packetdrill/logging.c         |  9 +++
 gtests/net/packetdrill/logging.h         |  2 +
 gtests/net/packetdrill/run.c             | 11 ++--
 gtests/net/packetdrill/run.h             | 12 ++--
 gtests/net/packetdrill/run_system_call.c | 71 +++++++++++++-----------
 gtests/net/packetdrill/wire_server.c     | 11 ++--
 6 files changed, 70 insertions(+), 46 deletions(-)

diff --git a/gtests/net/packetdrill/logging.c b/gtests/net/packetdrill/logging.c
index 730add4b..0b722845 100644
--- a/gtests/net/packetdrill/logging.c
+++ b/gtests/net/packetdrill/logging.c
@@ -49,3 +49,12 @@ void __attribute__((noreturn)) die_perror(char *message)
 
 	exit(EXIT_FAILURE);
 }
+
+void __attribute__((noreturn)) die_strerror(char *message, int err)
+{
+	fprintf(stderr, "%s: %s", message, strerror(err));
+
+	run_cleanup_command();
+
+	exit(EXIT_FAILURE);
+}
diff --git a/gtests/net/packetdrill/logging.h b/gtests/net/packetdrill/logging.h
index 2e17bd09..97487ef8 100644
--- a/gtests/net/packetdrill/logging.h
+++ b/gtests/net/packetdrill/logging.h
@@ -47,4 +47,6 @@ extern void __attribute__((noreturn)) die(char *format, ...);
 /* Call perror() with message and then exit with a failure status code. */
 extern void __attribute__((noreturn)) die_perror(char *message);
 
+/* Call strerror with with err and then exit with a failure status code. */
+extern void __attribute__((noreturn)) die_strerror(char *message, int err);
 #endif /* __LOGGING_H__ */
diff --git a/gtests/net/packetdrill/run.c b/gtests/net/packetdrill/run.c
index 217a0607..8467bb73 100644
--- a/gtests/net/packetdrill/run.c
+++ b/gtests/net/packetdrill/run.c
@@ -87,9 +87,10 @@ struct state *state_new(struct config *config,
 			struct netdev *netdev)
 {
 	struct state *state = calloc(1, sizeof(struct state));
+	int err;
 
-	if (pthread_mutex_init(&state->mutex, NULL) != 0)
-		die_perror("pthread_mutex_init");
+	if ((err = pthread_mutex_init(&state->mutex, NULL)) != 0)
+		die_strerror("pthread_mutex_init", err);
 
 	run_lock(state);
 
@@ -146,6 +147,8 @@ static void close_all_sockets(struct state *state)
 
 void state_free(struct state *state, int about_to_die)
 {
+	int err;
+
 	/* We have to stop the system call thread first, since it's using
 	 * sockets that we want to close and reset.
 	 */
@@ -162,8 +165,8 @@ void state_free(struct state *state, int about_to_die)
 	code_free(state->code);
 
 	run_unlock(state);
-	if (pthread_mutex_destroy(&state->mutex) != 0)
-		die_perror("pthread_mutex_destroy");
+	if ((err = pthread_mutex_destroy(&state->mutex)) != 0)
+		die_strerror("pthread_mutex_destroy", err);
 
 	memset(state, 0, sizeof(*state));  /* paranoia to help catch bugs */
 	free(state);
diff --git a/gtests/net/packetdrill/run.h b/gtests/net/packetdrill/run.h
index 6acb518b..ccba2fef 100644
--- a/gtests/net/packetdrill/run.h
+++ b/gtests/net/packetdrill/run.h
@@ -115,15 +115,19 @@ void state_free(struct state *state, int about_to_die);
 /* Grab the global lock for all global state. */
 static inline void run_lock(struct state *state)
 {
-	if (pthread_mutex_lock(&state->mutex) != 0)
-		die_perror("pthread_mutex_lock");
+	int err;
+
+	if ((err = pthread_mutex_lock(&state->mutex)) != 0)
+		die_strerror("pthread_mutex_lock", err);
 }
 
 /* Release the global lock for all global state. */
 static inline void run_unlock(struct state *state)
 {
-	if (pthread_mutex_unlock(&state->mutex) != 0)
-		die_perror("pthread_mutex_unlock");
+	int err;
+
+	if ((err = pthread_mutex_unlock(&state->mutex)) != 0)
+		die_strerror("pthread_mutex_unlock", err);
 }
 
 /* Get the wall clock time of day in microseconds. */
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 3bb73fc2..4a0d9396 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -1647,13 +1647,15 @@ static int pollfds_check(struct expression *fds_expression,
  */
 static void begin_syscall(struct state *state, struct syscall_spec *syscall)
 {
+	int err;
+
 	if (is_blocking_syscall(syscall)) {
 		assert(state->syscalls->state == SYSCALL_ENQUEUED);
 		state->syscalls->state = SYSCALL_RUNNING;
 		run_unlock(state);
 		DEBUGP("syscall thread: begin_syscall signals dequeued\n");
-		if (pthread_cond_signal(&state->syscalls->dequeued) != 0)
-			die_perror("pthread_cond_signal");
+		if ((err = pthread_cond_signal(&state->syscalls->dequeued)) != 0)
+			die_strerror("pthread_cond_signal", err);
 	}
 }
 
@@ -7002,12 +7004,12 @@ static int await_idle_thread(struct state *state)
 		}
 		/* Wait for a signal or our timeout end_time to arrive. */
 		DEBUGP("main thread: awaiting idle syscall thread\n");
-		int status = pthread_cond_timedwait(&state->syscalls->idle,
-						    &state->mutex, &end_time);
-		if (status == ETIMEDOUT)
+		int err = pthread_cond_timedwait(&state->syscalls->idle,
+						 &state->mutex, &end_time);
+		if (err == ETIMEDOUT)
 			return STATUS_ERR;
-		else if (status != 0)
-			die_perror("pthread_cond_timedwait");
+		else if (err != 0)
+			die_strerror("pthread_cond_timedwait", err);
 	}
 	return STATUS_OK;
 }
@@ -7034,6 +7036,7 @@ static void enqueue_system_call(
 	struct state *state, struct event *event, struct syscall_spec *syscall)
 {
 	char *error = NULL, *script_path = NULL;
+	int err;
 	bool done = false;
 
 	/* Wait if there are back-to-back blocking system calls. */
@@ -7046,16 +7049,16 @@ static void enqueue_system_call(
 	/* Enqueue the system call info and wake up the syscall thread. */
 	DEBUGP("main thread: signal enqueued\n");
 	state->syscalls->state = SYSCALL_ENQUEUED;
-	if (pthread_cond_signal(&state->syscalls->enqueued) != 0)
-		die_perror("pthread_cond_signal");
+	if ((err = pthread_cond_signal(&state->syscalls->enqueued)) != 0)
+		die_strerror("pthread_cond_signal", err);
 
 	/* Wait for the syscall thread to dequeue and start the system call. */
 	while (state->syscalls->state == SYSCALL_ENQUEUED) {
 		DEBUGP("main thread: waiting for dequeued signal; "
 		       "state: %d\n", state->syscalls->state);
-		if (pthread_cond_wait(&state->syscalls->dequeued,
-				      &state->mutex) != 0) {
-			die_perror("pthread_cond_wait");
+		if ((err = pthread_cond_wait(&state->syscalls->dequeued,
+					     &state->mutex)) != 0) {
+			die_strerror("pthread_cond_wait", err);
 		}
 	}
 
@@ -7127,6 +7130,7 @@ static void *system_call_thread(void *arg)
 	char *error = NULL;
 	struct event *event = NULL;
 	struct syscall_spec *syscall = NULL;
+	int err;
 	bool done = false;
 
 #if defined(__FreeBSD__)
@@ -7156,9 +7160,9 @@ static void *system_call_thread(void *arg)
 		switch (state->syscalls->state) {
 		case SYSCALL_IDLE:
 			DEBUGP("syscall thread: waiting\n");
-			if (pthread_cond_wait(&state->syscalls->enqueued,
-					      &state->mutex)) {
-				die_perror("pthread_cond_wait");
+			if ((err = pthread_cond_wait(&state->syscalls->enqueued,
+						     &state->mutex))) {
+				die_strerror("pthread_cond_wait", err);
 			}
 			break;
 
@@ -7209,8 +7213,8 @@ static void *system_call_thread(void *arg)
 			state->syscalls->event = NULL;
 			state->syscalls->live_end_usecs = -1;
 			DEBUGP("syscall thread: now idle\n");
-			if (pthread_cond_signal(&state->syscalls->idle) != 0)
-				die_perror("pthread_cond_signal");
+			if ((err = pthread_cond_signal(&state->syscalls->idle)) != 0)
+				die_strerror("pthread_cond_signal", err);
 			break;
 
 		case SYSCALL_EXITING:
@@ -7228,18 +7232,19 @@ static void *system_call_thread(void *arg)
 struct syscalls *syscalls_new(struct state *state)
 {
 	struct syscalls *syscalls = calloc(1, sizeof(struct syscalls));
+	int err;
 
 	syscalls->state = SYSCALL_IDLE;
 
-	if (pthread_create(&syscalls->thread, NULL, system_call_thread,
-			   state) != 0) {
-		die_perror("pthread_create");
+	if ((err = pthread_create(&syscalls->thread, NULL, system_call_thread,
+				  state)) != 0) {
+		die_strerror("pthread_create", err);
 	}
 
-	if ((pthread_cond_init(&syscalls->idle, NULL) != 0) ||
-	    (pthread_cond_init(&syscalls->enqueued, NULL) != 0) ||
-	    (pthread_cond_init(&syscalls->dequeued, NULL) != 0)) {
-		die_perror("pthread_cond_init");
+	if (((err= pthread_cond_init(&syscalls->idle, NULL)) != 0) ||
+	    ((err = pthread_cond_init(&syscalls->enqueued, NULL)) != 0) ||
+	    ((err = pthread_cond_init(&syscalls->dequeued, NULL)) != 0)) {
+		die_strerror("pthread_cond_init", err);
 	}
 
 	return syscalls;
@@ -7247,7 +7252,7 @@ struct syscalls *syscalls_new(struct state *state)
 
 void syscalls_free(struct state *state, struct syscalls *syscalls, int about_to_die)
 {
-	int status;
+	int status, err;
 
 	/* Wait a bit for the thread to go idle. */
 	status = await_idle_thread(state);
@@ -7266,21 +7271,21 @@ void syscalls_free(struct state *state, struct syscalls *syscalls, int about_to_
 		/* Send a request to terminate the thread. */
 		DEBUGP("main thread: signaling syscall thread to exit\n");
 		syscalls->state = SYSCALL_EXITING;
-		if (pthread_cond_signal(&syscalls->enqueued) != 0)
-			die_perror("pthread_cond_signal");
+		if ((err = pthread_cond_signal(&syscalls->enqueued)) != 0)
+			die_strerror("pthread_cond_signal", err);
 	}
 	/* Release the lock briefly and wait for syscall thread to finish. */
 	run_unlock(state);
 	DEBUGP("main thread: unlocking, waiting for syscall thread exit\n");
 	void *thread_result = NULL;
-	if (pthread_join(syscalls->thread, &thread_result) != 0)
-		die_perror("pthread_cancel");
+	if ((err = pthread_join(syscalls->thread, &thread_result)) != 0)
+		die_strerror("pthread_join", err);
 	DEBUGP("main thread: joined syscall thread; relocking\n");
 	run_lock(state);
-	if ((pthread_cond_destroy(&syscalls->idle) != 0) ||
-	    (pthread_cond_destroy(&syscalls->enqueued) != 0) ||
-	    (pthread_cond_destroy(&syscalls->dequeued) != 0)) {
-		die_perror("pthread_cond_destroy");
+	if (((err = pthread_cond_destroy(&syscalls->idle)) != 0) ||
+	    ((err = pthread_cond_destroy(&syscalls->enqueued)) != 0) ||
+	    ((err = pthread_cond_destroy(&syscalls->dequeued)) != 0)) {
+		die_strerror("pthread_cond_destroy", err);
 	}
 
 	memset(syscalls, 0, sizeof(*syscalls));  /* to help catch bugs */
diff --git a/gtests/net/packetdrill/wire_server.c b/gtests/net/packetdrill/wire_server.c
index 6e722dc7..c9923f14 100644
--- a/gtests/net/packetdrill/wire_server.c
+++ b/gtests/net/packetdrill/wire_server.c
@@ -504,12 +504,13 @@ error_done:
 
 static void start_wire_server_thread(struct wire_server *wire_server)
 {
-	DEBUGP("start_wire_server_thread\n");
-
 	pthread_t thread;		/* pthread thread handle */
-	if (pthread_create(&thread, NULL, wire_server_thread,
-			   wire_server) != 0) {
-		die_perror("pthread_create");
+	int err;
+
+	DEBUGP("start_wire_server_thread\n");
+	if ((err = pthread_create(&thread, NULL, wire_server_thread,
+				  wire_server)) != 0) {
+		die_strerror("pthread_create", err);
 	}
 }
 
-- 
GitLab