Browse Source

Merge branch 'develop'

master v0.2.0
Damien Goutte-Gattat 9 years ago
parent
commit
6afba982ad
  1. 2
      Makefile.am
  2. 5
      NEWS
  3. 7
      README
  4. 6
      configure.ac
  5. 2
      lib/Makefile.am
  6. 0
      lib/dummy.c
  7. 79
      lib/xmem.c
  8. 52
      lib/xmem.h
  9. 19
      src/wait4.c
  10. 100
      src/wait4pid.c
  11. 5
      src/wait4pid.h

2
Makefile.am

@ -2,4 +2,4 @@ SUBDIRS = lib src
ACLOCAL_AMFLAGS = -I m4 --install
dist_doc_DATA = AUTHORS COPYING README
dist_doc_DATA = AUTHORS COPYING NEWS README

5
NEWS

@ -0,0 +1,5 @@
Changes in wait4 0.2.0
* Wait for several processes at once.
* Do not wait for inexistent processes when using Netlink.
* Replace the /proc-based default mode by a kill(2)-based mode.

7
README

@ -11,9 +11,10 @@ current shell.
On GNU/Linux systems where the Netlink interface is available, wait4 is
directly informed by the kernel as soon as the target process is
terminated, and the exit code of that process is used as the exit code
of wait4 itself. On other systems, wait4 acts by polling the /proc
filesystem every second; in that case, the exit code is always 0, as
there is no way to retrieve the exit code of the target process.
of wait4 itself. On other systems, wait4 acts by pretending to send a
signal to the target process every second; in that case, the exit code
is always 0, as there is no way to retrieve the exit code of the target
process.
When using Netlink, wait4 must be run as setuid root, as only a
privileged process can bind to an AF_NETLINK address; root privileges

6
configure.ac

@ -1,6 +1,6 @@
dnl Configure template for the wait4 package
AC_INIT([wait4], [0.1.0],
AC_INIT([wait4], [0.2.0],
[dgouttegattat@incenp.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
@ -18,8 +18,8 @@ AC_PROG_INSTALL
dnl Check for some non-ubituitous functions
ICP_CHECK_NOTCH_FUNCS
dnl Check for possible mechanism, default is /proc
backend="/proc"
dnl Check for possible mechanism, default is kill
backend="kill"
AC_CHECK_HEADERS([linux/netlink.h],
[backend=Netlink])
AM_CONDITIONAL([HAVE_NETLINK], [test x$ac_cv_header_linux_netlink_h = xyes])

2
lib/Makefile.am

@ -1,5 +1,5 @@
noinst_LIBRARIES = libwait4.a
libwait4_a_SOURCES = err.compat.h compat.h dummy.c
libwait4_a_SOURCES = err.compat.h compat.h xmem.c xmem.h
libwait4_a_LIBADD = $(LIBOBJS)

0
lib/dummy.c

79
lib/xmem.c

@ -0,0 +1,79 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <xmem.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
void (*xmem_error)(const char *, unsigned int) = NULL;
#define mem_error(f, l) \
do { \
if ( xmem_error ) \
(*xmem_error)((f), (l)); \
err(EXIT_FAILURE, "%s, %d", (f), (l)); \
} while ( 0 )
void *
do_malloc(size_t s, const char *file, unsigned int line)
{
void *p;
if ( ! (p = malloc(s)) && s )
mem_error(file, line);
return p;
}
void *
do_calloc(size_t n, size_t s, const char *file, unsigned int line)
{
void *p;
if ( ! (p = calloc(n, s)) && n && s )
mem_error(file, line);
return p;
}
void *
do_realloc(void *p, size_t s, const char *file, unsigned int line)
{
void *np;
if ( ! (np = realloc(p, s)) && s )
mem_error(file, line);
return np;
}
char *
do_strdup(const char *s, const char *file, unsigned int line)
{
char *dup;
if ( ! (dup = strdup(s)) && s )
mem_error(file, line);
return dup;
}

52
lib/xmem.h

@ -0,0 +1,52 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20110203_XMEM_H
#define ICP20110203_XMEM_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef __cpluscplus
extern "C" {
#endif
extern void (*xmem_error)(const char *, unsigned int);
void *
do_malloc(size_t, const char *, unsigned int);
void *
do_calloc(size_t, size_t, const char *, unsigned int);
void *
do_realloc(void *, size_t, const char *, unsigned int);
char *
do_strdup(const char *, const char *, unsigned int);
#define xmalloc(s) do_malloc(s, __FILE__, __LINE__)
#define xcalloc(n,s) do_calloc(n, s, __FILE__, __LINE__)
#define xrealloc(p,s) do_realloc(p, s, __FILE__, __LINE__)
#define xstrdup(s) do_strdup(s, __FILE__, __LINE__)
#ifdef __cplusplus
}
#endif
#endif /* !ICP20110203_XMEM_H */

19
src/wait4.c

@ -25,6 +25,8 @@
#include <getopt.h>
#include <errno.h>
#include <err.h>
#include <xmem.h>
#include <wait4pid.h>
/* Help and informations about the program. */
@ -32,8 +34,9 @@
static void
usage(int status)
{
puts("Usage: wait4 pid\n\
Wait until the specified process terminates.\n");
puts("Usage: wait4 pid[,...]\n\
Waits until the specified process terminates. If more than one\n\
PID is specified, waits for all of them.\n");
puts("Options:\n\
-h, --help Display this help message.\n\
@ -82,7 +85,7 @@ get_integer_or_die(const char *arg)
int
main(int argc, char **argv)
{
int c, pid, ec;
int c, ec, len, *pids, i;
struct option options[] = {
{ "help", 0, NULL, 'h' },
@ -108,13 +111,15 @@ main(int argc, char **argv)
}
}
if ( argc - optind != 1 )
if ( (len = argc - optind) < 1 )
usage(EXIT_FAILURE);
pid = get_integer_or_die(argv[optind]);
pids = xmalloc(len * sizeof(int));
for ( i = 0; i < len; i++ )
pids[i] = get_integer_or_die(argv[optind + i]);
if ( (ec = wait4pid(pid)) == -1 )
err(EXIT_FAILURE, "cannot wait for process %d", pid);
if ( (ec = wait4all(pids, len)) == -1 )
err(EXIT_FAILURE, "cannot wait for processes");
return ec;
}

100
src/wait4pid.c

@ -24,6 +24,7 @@
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/connector.h>
@ -97,21 +98,38 @@ wait4pid_init(void)
return 0;
}
struct __attribute__ ((__packed__)) cn_proc_msg {
struct cn_msg msg;
struct proc_event evt;
};
static int
do_recv(int sock, void *buf, size_t len, int flags)
{
int ret;
do {
ret = recv(sock, buf, len, flags);
} while ( ret == -1 && errno == EINTR );
return ret;
}
int
wait4pid(pid_t pid)
{
int ec;
struct __attribute__ ((__packed__)) payload_t {
struct cn_msg msg;
struct proc_event evt;
} *payload;
char buf[NLMSG_SPACE(sizeof(struct payload_t))];
struct cn_proc_msg *payload;
char buf[NLMSG_SPACE(sizeof(struct cn_proc_msg))];
if ( ! listener_set && wait4pid_init() == -1 )
return -1;
while ( recv(sock, buf, sizeof(buf), 0) > 0 ) {
payload = (struct payload_t *) NLMSG_DATA(buf);
if ( kill(pid, 0) == -1 && errno == ESRCH )
return -1;
while ( do_recv(sock, buf, sizeof(buf), 0) > 0 ) {
payload = (struct cn_proc_msg *) NLMSG_DATA(buf);
if ( payload->evt.what == PROC_EVENT_EXIT
&& payload->evt.event_data.exit.process_pid == pid ) {
ec = payload->evt.event_data.exit.exit_code / 256;
@ -122,22 +140,76 @@ wait4pid(pid_t pid)
return ec;
}
int
wait4all(pid_t *pids, size_t len)
{
int ec, nproc, i;
struct cn_proc_msg *payload;
char buf[NLMSG_SPACE(sizeof(struct cn_proc_msg))];
if ( ! listener_set && wait4pid_init() == -1 )
return -1;
for ( i = 0; i < len; i++ ) {
if ( kill(pids[i], 0) == -1 && errno == ESRCH )
return -1;
}
nproc = len;
while ( nproc > 0 ) {
if ( do_recv(sock, buf, sizeof(buf), 0) <= 0 )
return -1;
payload = (struct cn_proc_msg *) NLMSG_DATA(buf);
if ( payload->evt.what != PROC_EVENT_EXIT )
continue;
for ( i = 0; i < len; i++ ) {
if ( pids[i] != -1
&& pids[i] == payload->evt.event_data.exit.process_pid ) {
pids[i] = -1;
nproc -= 1;
if ( i == len - 1 )
ec = payload->evt.event_data.exit.exit_code / 256;
}
}
}
return ec;
}
#else /* HAVE_LINUX_NETLINK_H */
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
int
wait4pid(pid_t pid)
{
struct stat st_buf;
char path[20];
while ( kill(pid, 0) != -1 || errno != ESRCH )
sleep(1);
snprintf(path, sizeof(path), "/proc/%d", pid);
return 0;
}
int
wait4all(pid_t *pids, size_t len)
{
int nproc, i;
nproc = len;
while ( nproc > 0 ) {
for ( i = 0; i < len; i++ ) {
if ( pids[i] == -1 )
continue;
if ( kill(pids[i], 0) == -1 && errno == ESRCH ) {
pids[i] = -1;
nproc -= 1;
}
}
while ( stat(path, &st_buf) != -1 )
sleep(1);
}
return 0;
}

5
src/wait4pid.h

@ -19,6 +19,8 @@
#ifndef ICP20130319_WAIT4PID_H
#define ICP20130319_WAIT4PID_H
#include <stdlib.h>
#ifdef __cpluscplus
extern "C" {
#endif
@ -26,6 +28,9 @@ extern "C" {
int
wait4pid(pid_t);
int
wait4all(pid_t *, size_t);
#ifdef __cplusplus
}
#endif

Loading…
Cancel
Save