#include <errno.h>
#include <signal.h>
#include <string.h>
+#include <stdlib.h>
#include <unistd.h>
#include "log.h"
#include "io.h"
+#include "conn.h"
#include "exp.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;
return -1;
case 0:
/* New child process: */
+ signal(SIGTERM, Proc_GenericSignalHandler);
+ signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]);
+ alarm(timeout);
+ Conn_CloseAllSockets();
return 0;
}
}
/**
- * Kill forked child process.
+ * Generic signal handler for forked child processes.
*/
GLOBAL void
-Proc_Kill(PROC_STAT *proc)
+Proc_GenericSignalHandler(int Signal)
{
- assert(proc != NULL);
- assert(proc->pipe_fd >= 0);
+ switch(Signal) {
+ 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);
+ }
+}
- io_close(proc->pipe_fd);
- kill(proc->pid, SIGTERM);
+/**
+ * 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- */