File psmisc-23.0-semaphores.patch of Package psmisc.23622

Use semaphores for synchronize the stating sub process

---
 Makefile.am   |    2 
 src/timeout.c |  130 ++++++++++++++++++++++++----------------------------------
 2 files changed, 56 insertions(+), 76 deletions(-)

--- Makefile.am
+++ Makefile.am	2022-03-02 14:48:10.996587471 +0000
@@ -61,7 +61,7 @@ src_fuser_SOURCES = \
 if WANT_TIMEOUT_STAT
 src_fuser_SOURCES += src/timeout.c src/timeout.h
 endif
-src_fuser_LDADD = @LIBINTL@
+src_fuser_LDADD = @LIBINTL@ -lpthread
 src_killall_SOURCES = src/killall.c src/comm.h src/signals.c src/signals.h src/i18n.h
 src_killall_LDADD = @LIBINTL@ @SELINUX_LIB@
 src_peekfd_SOURCES = src/peekfd.c
--- src/timeout.c
+++ src/timeout.c	2022-03-01 09:05:31.374592643 +0000
@@ -27,11 +27,8 @@
 # define WITH_TIMEOUT_STAT	0
 #endif
 
-#ifndef USE_SOCKETPAIR
-# define USE_SOCKETPAIR		1
-#endif
-
 #include <errno.h>
+#include <pthread.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -42,20 +39,6 @@
 #include <sys/select.h>
 #include <sys/stat.h>
 #include <unistd.h>
-#if USE_SOCKETPAIR
-# include <sys/socket.h>
-# include <netdb.h>
-# include <netinet/in.h>
-#  ifndef SHUT_RD
-#   define SHUT_RD	0
-# endif
-# ifndef SHUT_WR
-#  define SHUT_WR	1
-# endif
-# undef pipe
-# define pipe(v)	(((socketpair(AF_UNIX,SOCK_STREAM,0,v) < 0) || \
-			(shutdown((v)[1],SHUT_RD) < 0) || (shutdown((v)[0],SHUT_WR) < 0)) ? -1 : 0)
-#endif
 #include <wait.h>
 
 #include "timeout.h"
@@ -102,6 +85,10 @@ static void sigjump(int sig attribute((u
  * The structure used for communication between the processes
  */
 typedef struct _handle {
+	pthread_mutex_t mutex;
+	pthread_cond_t waiton, result;
+	volatile int todo;
+	pid_t active;
 	int errcode;
 	struct stat argument;
 	stat_t function;
@@ -117,8 +104,7 @@ typedef struct _handle {
  */
 
 static volatile pid_t active;
-static int pipes[4] = {-1, -1, -1, -1};
-static handle_t *restrict handle;
+static handle_t *handle;
 static const size_t buflen = PATH_MAX+sizeof(handle_t)+1;
 
 static void sigchild(int sig attribute((unused)))
@@ -135,16 +121,8 @@ static void attribute((constructor)) sta
 {
 	sigset_t sigset, oldset;
 	struct sigaction act;
-	char sync[1];
-	ssize_t in;
-
-	if (pipes[1] >= 0) close(pipes[1]);
-	if (pipes[2] >= 0) close(pipes[2]);
-
-	if (pipe(&pipes[0]))
-		goto error;
-	if (pipe(&pipes[2]))
-		goto error;
+	pthread_mutexattr_t mattr;
+	pthread_condattr_t cattr;
 
 	memset(&act, 0, sizeof(act));
 	sigemptyset(&act.sa_mask);
@@ -152,22 +130,40 @@ static void attribute((constructor)) sta
 	act.sa_handler = sigchild;
 	sigaction(SIGCHLD, &act, 0);
 
-	if (!handle)
+	if (!handle) {
 		handle = mmap(NULL, buflen, PROT_READ|PROT_WRITE,
 			      MAP_ANONYMOUS|MAP_SHARED, -1, 0);
-	if (handle == MAP_FAILED)
-		goto error;
+		if (handle == MAP_FAILED)
+			goto error;
+		memset(handle, 0, buflen);
+
+		if (pthread_mutexattr_init(&mattr) < 0)
+			goto error;
+		if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED) < 0)
+			goto error;
+		if (pthread_mutex_init(&handle->mutex, &mattr) < 0)
+			goto error;
+		pthread_mutexattr_destroy(&mattr);
+
+		if (pthread_condattr_init(&cattr) < 0)
+			goto error;
+		if (pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED) < 0)
+			goto error;
+		if (pthread_cond_init(&handle->waiton, &cattr) < 0)
+			goto error;
+		if (pthread_cond_init(&handle->result, &cattr) < 0)
+			goto error;
+		pthread_condattr_destroy(&cattr);
+	}
 
+	handle->todo = 0;
 	if ((active = fork()) < 0)
 		goto error;
 
 	if (active) {
-		close(pipes[0]);
-		close(pipes[3]);
-		pipes[0] = pipes[3] = -1;
+		handle->active = active;
 		return;
 	}
-
 	sigemptyset(&sigset);
 	sigaddset(&sigset, SIGALRM);
 	sigprocmask(SIG_BLOCK, &sigset, &oldset);
@@ -175,44 +171,29 @@ static void attribute((constructor)) sta
 	act.sa_handler = SIG_DFL;
 	sigaction(SIGCHLD, &act, 0);
 
-	close(pipes[1]);
-	close(pipes[2]);
-	dup2(pipes[0], STDIN_FILENO);
-	dup2(pipes[3], STDOUT_FILENO);
-	close(pipes[0]);
-	close(pipes[3]);
-	pipes[1] = pipes[2] = -1;
-	pipes[0] = pipes[3] = -1;
-
-	while ((in = read(STDIN_FILENO, &sync, sizeof(sync))) != 0) {
-		ssize_t out;
-		if (in < 0) {
-			if (errno == EINTR)
-				continue;
-			break;
-		}
-		if (!handle)
-			break;
+	do {
+		pthread_mutex_lock(&handle->mutex);
+		while (!handle->todo)
+			pthread_cond_wait(&handle->waiton, &handle->mutex);
+
 		if (handle->function(handle->path, &handle->argument) < 0)
-				handle->errcode = errno;
-		do
-			out = write(STDOUT_FILENO, &sync, sizeof(sync));
-		while (out < 0 && errno == EINTR);
-	}
+			handle->errcode = errno;
+
+		handle->todo = 0;
+		pthread_cond_broadcast(&handle->result);
+		pthread_mutex_unlock(&handle->mutex);
+
+	} while (handle->active);
 
 	sigprocmask(SIG_SETMASK, &oldset, NULL);
 	exit(0);
 error:
-	if (pipes[0] >= 0) close(pipes[0]);
-	if (pipes[1] >= 0) close(pipes[1]);
-	if (pipes[2] >= 0) close(pipes[2]);
-	if (pipes[3] >= 0) close(pipes[3]);
 	if (handle && handle != MAP_FAILED)
 		munmap(handle, buflen);
 	handle = NULL;
 }
 
-static void /* attribute((destructor)) */ stop(void)
+static void attribute((destructor)) stop(void)
 {
 	if (active && waitpid(active, NULL, WNOHANG|WUNTRACED) == 0)
 		kill(active, SIGKILL);
@@ -228,15 +209,14 @@ static void /* attribute((destructor)) *
 int
 timeout(stat_t function, const char *path, struct stat *restrict argument, time_t seconds)
 {
-	struct sigaction alrm_act, pipe_act, new_act;
+	struct sigaction alrm_act, new_act;
 	sigset_t sigset, oldset;
-	char sync[1] = "x";
 
 	if (active <= 0)	/* Oops, last one failed therefore clear status and restart */
 		start();
 	if (!handle)		/* No shared memory area */
 		return function(path, argument);
-	memset(handle, 0, sizeof(handle_t));
+
 	handle->len = strlen(path) + 1;
 	if (handle->len >= PATH_MAX) {
 		errno = ENAMETOOLONG;
@@ -249,26 +229,27 @@ timeout(stat_t function, const char *pat
 
 	sigemptyset(&sigset);
 	sigaddset(&sigset, SIGALRM);
-	sigaddset(&sigset, SIGPIPE);
+	sigaddset(&sigset, SIGINT);
 	sigprocmask(SIG_UNBLOCK, &sigset, &oldset);
 
 	memset(&new_act, 0, sizeof(new_act));
 	sigemptyset(&new_act.sa_mask);
 	new_act.sa_flags = SA_RESETHAND;
-
 	if (sigsetjmp(jenv, 1))
 		goto timed;
 
 	new_act.sa_handler = sigjump;
 	sigaction(SIGALRM, &new_act, &alrm_act);
-	sigaction(SIGPIPE, &new_act, &pipe_act);
 	alarm(seconds);
 
-	write(pipes[1], &sync, sizeof(sync));
-	read(pipes[2], &sync, sizeof(sync));
+	pthread_mutex_lock(&handle->mutex);
+	handle->todo = 1;
+	pthread_cond_broadcast(&handle->waiton);
+	while (handle->todo)
+		pthread_cond_wait(&handle->result, &handle->mutex);
+	pthread_mutex_unlock(&handle->mutex);
 
 	alarm(0);
-	sigaction(SIGPIPE, &pipe_act, NULL);
 	sigaction(SIGALRM, &alrm_act, NULL);
 
 	if (handle->errcode) {
@@ -282,7 +263,6 @@ timeout(stat_t function, const char *pat
 	return 0;
 timed:
 	(void) alarm(0);
-	sigaction(SIGPIPE, &pipe_act, NULL);
 	sigaction(SIGALRM, &alrm_act, NULL);
 	sigprocmask(SIG_SETMASK, &oldset, NULL);
 	stop();
openSUSE Build Service is sponsored by