Hello community,
here is the log from the commit of package psmisc for openSUSE:Factory
checked in at Fri Oct 7 17:07:37 CEST 2011.
--------
--- openSUSE:Factory/psmisc/psmisc.changes 2011-10-05 17:47:29.000000000 +0200
+++ /mounts/work_src_done/STABLE/psmisc/psmisc.changes 2011-10-07 16:12:00.000000000 +0200
@@ -1,0 +2,6 @@
+Fri Oct 7 14:08:31 UTC 2011 - werner@suse.de
+
+- Make main fuser process more robust against broken pipe and check
+ for helper process within a SIGCHLD handler
+
+-------------------------------------------------------------------
calling whatdependson for head-i586
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ psmisc-22.15-timeout.patch ++++++
--- /var/tmp/diff_new_pack.8QpXDu/_old 2011-10-07 17:07:34.000000000 +0200
+++ /var/tmp/diff_new_pack.8QpXDu/_new 2011-10-07 17:07:34.000000000 +0200
@@ -117,10 +117,10 @@
/*
* Use /proc/self/mountinfo of modern linux system to determine
diff --git a/src/timeout.c b/src/timeout.c
-index e69de29..3b582a3 100644
+index e69de29..e79774b 100644
--- a/src/timeout.c
+++ b/src/timeout.c
-@@ -0,0 +1,215 @@
+@@ -0,0 +1,260 @@
+/*
+ * timout.c Advanced timeout handling for file system calls
+ * to avoid deadlocks on remote file shares.
@@ -138,9 +138,16 @@
+ */
+
+#ifndef _GNU_SOURCE
-+#define _GNU_SOURCE
++# define _GNU_SOURCE
+#endif
+
++#ifndef USE_SOCKETPAIR
++# define USE_SOCKETPAIR 1
++#endif
++
++#ifdef _FEATURES_H
++# error Include local config.h before any system header file
++#endif
+#include "config.h" /* For _FILE_OFFSET_BITS */
+
+#include
@@ -153,10 +160,24 @@
+#include
+#include
+#include
++
+#include
++#if USE_SOCKETPAIR
++# include
++# include
++# include
++# 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
+
-+#include
+#include "timeout.h"
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
@@ -186,16 +207,14 @@
+/*
+ * The structure used for communication between the processes
+ */
-+
+typedef struct _handle {
-+ size_t len;
+ int errcode;
+ struct stat argument;
+ stat_t function;
++ size_t len;
++ char path[0];
+} attribute((packed)) handle_t;
+
-+static volatile handle_t handle;
-+
+/*
+ * Using a forked process for doing e.g. stat(2) system call as this
+ * allows us to send e.g. SIGKILL to this process if it hangs in `D'
@@ -205,44 +224,72 @@
+
+static volatile pid_t active;
+static int pipes[4] = {-1, -1, -1, -1};
++static char buf[PATH_MAX + sizeof(handle_t) + 1];
++
++static void sigchild(int sig attribute((unused)))
++{
++ pid_t pid = waitpid(active, NULL, WNOHANG|WUNTRACED);
++ if (pid <= 0)
++ return;
++ if (errno == ECHILD)
++ return;
++ active = 0;
++}
+
+static void attribute((constructor)) start(void)
+{
+ sigset_t sigset, oldset;
-+ char path[PATH_MAX];
-+ handle_t handle;
++ struct sigaction act;
+ 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;
++
++ memset(&act, 0, sizeof(act));
++ sigemptyset(&act.sa_mask);
++ act.sa_flags = SA_RESTART;
++ act.sa_handler = sigchild;
++ sigaction(SIGCHLD, &act, 0);
++
+ if ((active = fork()) < 0)
+ goto error;
++
+ if (active) {
+ close(pipes[0]);
+ close(pipes[3]);
+ pipes[0] = pipes[3] = -1;
+ return;
+ }
++
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGALRM);
+ sigprocmask(SIG_BLOCK, &sigset, &oldset);
+
++ act.sa_handler = SIG_DFL;
++ sigaction(SIGCHLD, &act, 0);
++
+ close(pipes[1]);
+ close(pipes[2]);
-+ dup2(pipes[0], 0);
-+ dup2(pipes[3], 1);
++ 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(0, &handle, sizeof(handle_t))) == sizeof(handle_t) &&
-+ (in = read(0, path, handle.len)) == handle.len) {
-+ if (handle.function(path, &handle.argument) < 0)
-+ handle.errcode = errno;
-+ write(1, &handle.errcode, sizeof(handle.errcode)+sizeof(handle.argument));
++ {
++ handle_t *restrict handle = (void*)&buf[0];
++
++ while ((in = read(STDIN_FILENO, handle, sizeof(buf))) > sizeof(handle_t)) {
++ if (handle->function(handle->path, &handle->argument) < 0)
++ handle->errcode = errno;
++ write(STDOUT_FILENO, &handle->errcode, sizeof(handle->errcode)+sizeof(handle->argument));
++ }
+ }
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ exit(0);
@@ -255,15 +302,12 @@
+
+static void /* attribute((destructor)) */ stop(void)
+{
-+ if (active <= 0)
-+ return;
-+ if (waitpid(active, NULL, WNOHANG) == 0)
++ if (active && waitpid(active, NULL, WNOHANG|WUNTRACED) == 0)
+ kill(active, SIGKILL);
-+ active = 0;
+}
+
+static sigjmp_buf jenv;
-+static void sigalarm(int sig attribute((unused)))
++static void sigjump(int sig attribute((unused)))
+{
+ siglongjmp(jenv, 1);
+}
@@ -271,61 +315,62 @@
+/*
+ * External routine
+ */
-+
+int timeout(stat_t function, const char *path, struct stat *restrict argument, time_t seconds)
+{
-+ struct sigaction old_act, new_act;
++ handle_t *restrict handle = (void*)&buf[0];
++ struct sigaction alrm_act, pipe_act, new_act;
+ sigset_t sigset, oldset;
+
-+ if (active <= 0) { /* Oops, last one failed therefore clear status and restart */
-+ int status;
-+ waitpid(-1, &status, WNOHANG);
++ if (active <= 0) /* Oops, last one failed therefore clear status and restart */
+ start();
-+ }
+
-+ handle.len = strlen(path) + 1;
-+ if (handle.len >= PATH_MAX) {
++ handle->len = strlen(path) + 1;
++ if (handle->len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ goto error;
+ }
-+ handle.errcode = 0;
-+ handle.argument = *argument;
-+ handle.function = function;
++ handle->errcode = 0;
++ handle->argument = *argument;
++ handle->function = function;
++ strcpy(handle->path, path);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGALRM);
++ sigaddset(&sigset, SIGPIPE);
+ sigprocmask(SIG_UNBLOCK, &sigset, &oldset);
+
+ memset(&new_act, 0, sizeof(new_act));
+ sigemptyset(&new_act.sa_mask);
+ new_act.sa_flags = SA_RESETHAND;
-+ new_act.sa_handler = sigalarm;
+
+ if (sigsetjmp(jenv, 1))
+ goto timed;
+
-+ sigaction(SIGALRM, &new_act, &old_act);
++ new_act.sa_handler = sigjump;
++ sigaction(SIGALRM, &new_act, &alrm_act);
++ sigaction(SIGPIPE, &new_act, &pipe_act);
+ alarm(seconds);
+
-+ write(pipes[1], &handle, sizeof(handle_t));
-+ write(pipes[1], path, handle.len);
-+ sched_yield();
-+ read(pipes[2], &handle.errcode, sizeof(handle.errcode)+sizeof(handle.argument));
++ write(pipes[1], handle, sizeof(handle_t)+handle->len);
++ read(pipes[2], &handle->errcode, sizeof(handle->errcode)+sizeof(handle->argument));
+
+ alarm(0);
-+ sigaction(SIGALRM, &old_act, NULL);
++ sigaction(SIGPIPE, &pipe_act, NULL);
++ sigaction(SIGALRM, &alrm_act, NULL);
+
-+ if (handle.errcode) {
-+ errno = handle.errcode;
++ if (handle->errcode) {
++ errno = handle->errcode;
+ goto error;
+ }
+
-+ *argument = handle.argument;
++ *argument = handle->argument;
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+
+ return 0;
+timed:
+ (void) alarm(0);
++ sigaction(SIGPIPE, &pipe_act, NULL);
++ sigaction(SIGALRM, &alrm_act, NULL);
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ stop();
+ errno = ETIMEDOUT;
@@ -337,7 +382,7 @@
+ * End of timeout.c
+ */
diff --git a/src/timeout.h b/src/timeout.h
-index e69de29..50dd135 100644
+index e69de29..546c13b 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -0,0 +1,36 @@
continue with "q"...
Remember to have fun...
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org