* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
- *
- * Process management
*/
#include "portab.h"
+/**
+ * @file
+ * Process management
+ */
+
#include "imp.h"
#include <assert.h>
#include <errno.h>
#include "log.h"
#include "io.h"
+#include "conn.h"
#include "exp.h"
+#include "sighandlers.h"
#include "proc.h"
/**
* Fork a child process.
*/
GLOBAL pid_t
-Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short))
+Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout)
{
pid_t pid;
+ unsigned int seed;
assert(proc != NULL);
assert(pipefds != NULL);
return -1;
}
+ seed = (unsigned int)random();
pid = fork();
switch (pid) {
case -1:
return -1;
case 0:
/* New child process: */
+ srandom(seed ^ (unsigned int)time(NULL) ^ getpid());
+ Signals_Exit();
+ signal(SIGTERM, Proc_GenericSignalHandler);
+ signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]);
+ alarm(timeout);
+ Conn_CloseAllSockets();
return 0;
}
return pid;
}
-/**
- * Kill forked child process.
- */
-GLOBAL void
-Proc_Kill(PROC_STAT *proc)
-{
- assert(proc != NULL);
- assert(proc->pipe_fd >= 0);
-
- io_close(proc->pipe_fd);
- kill(proc->pid, SIGTERM);
- Proc_InitStruct(proc);
-}
-
/**
* Generic signal handler for forked child processes.
*/
case SIGTERM:
#ifdef DEBUG
Log_Subprocess(LOG_DEBUG, "Child got TERM signal, exiting.");
+#endif
+ exit(1);
+ case SIGALRM:
+#ifdef DEBUG
+ Log_Subprocess(LOG_DEBUG, "Child got ALARM signal, exiting.");
#endif
exit(1);
}
}
+/**
+ * Read bytes from a pipe of a forked child process.
+ * In addition, this function makes sure that the child process is ignored
+ * after all data has been read or a fatal error occurred.
+ */
+GLOBAL size_t
+Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
+{
+ ssize_t bytes_read = 0;
+
+ assert(buffer != NULL);
+ assert(buflen > 0);
+
+ bytes_read = read(proc->pipe_fd, buffer, buflen);
+ if (bytes_read < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ Log(LOG_CRIT, "Can't read from child process %ld: %s",
+ proc->pid, strerror(errno));
+ bytes_read = 0;
+ }
+#if DEBUG
+ else if (bytes_read == 0)
+ LogDebug("Can't read from child process %ld: EOF", proc->pid);
+#endif
+ Proc_InitStruct(proc);
+ return (size_t)bytes_read;
+}
+
/* -eof- */