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();