* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: main.c,v 1.138 2004/10/28 00:32:32 paulus Exp $"
+#define RCSID "$Id: main.c,v 1.139 2004/11/04 09:46:50 paulus Exp $"
#include <stdio.h>
#include <ctype.h>
int doing_callback; /* != 0 if we are doing callback */
int ppp_session_number; /* Session number, for channels with such a
concept (eg PPPoE) */
+int childwait_done; /* have timed out waiting for children */
+
#ifdef USE_TDB
TDB_CONTEXT *pppdb; /* database for storing status etc. */
#endif
static void open_ccp __P((int));
static void bad_signal __P((int));
static void holdoff_end __P((void *));
-static int reap_kids __P((int waitfor));
+static int reap_kids __P((void));
+static void childwait_end __P((void *));
#ifdef USE_TDB
static void update_db_entry __P((void));
}
/* Wait for scripts to finish */
- /* XXX should have a timeout here */
- while (n_children > 0) {
+ reap_kids();
+ if (n_children > 0) {
+ if (child_wait > 0)
+ TIMEOUT(childwait_end, NULL, child_wait);
if (debug) {
struct subprocess *chp;
dbglog("Waiting for %d child processes...", n_children);
for (chp = children; chp != NULL; chp = chp->next)
dbglog(" script %s, pid %d", chp->prog, chp->pid);
}
- if (reap_kids(1) < 0)
- break;
+ while (n_children > 0 && !childwait_done) {
+ handle_events();
+ if (kill_link && !childwait_done)
+ childwait_end(NULL);
+ }
}
die(status);
got_sigterm = 0;
}
if (got_sigchld) {
- reap_kids(0); /* Don't leave dead kids lying around */
got_sigchld = 0;
+ reap_kids(); /* Don't leave dead kids lying around */
}
if (got_sigusr2) {
open_ccp_flag = 1;
}
}
+/*
+ * childwait_end - we got fed up waiting for the child processes to
+ * exit, send them all a SIGTERM.
+ */
+static void
+childwait_end(arg)
+ void *arg;
+{
+ struct subprocess *chp;
+
+ for (chp = children; chp != NULL; chp = chp->next) {
+ if (debug)
+ dbglog("sending SIGTERM to process %d", chp->pid);
+ kill(chp->pid, SIGTERM);
+ }
+ childwait_done = 1;
+}
/*
* reap_kids - get status from any dead child processes,
* and log a message for abnormal terminations.
*/
static int
-reap_kids(waitfor)
- int waitfor;
+reap_kids()
{
int pid, status;
struct subprocess *chp, **prevp;
if (n_children == 0)
return 0;
- while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
- && pid != 0) {
+ while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) {
for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
if (chp->pid == pid) {
--n_children;
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: options.c,v 1.93 2004/10/28 00:15:08 paulus Exp $"
+#define RCSID "$Id: options.c,v 1.94 2004/11/04 09:46:50 paulus Exp $"
#include <ctype.h>
#include <stdio.h>
bool dump_options; /* print out option values */
bool dryrun; /* print out option values and exit */
char *domain; /* domain name set by domain option */
+int child_wait = 5; /* # seconds to wait for children at exit */
#ifdef MAXOCTETS
unsigned int maxoctets = 0; /* default - no limit */
{ "dryrun", o_bool, &dryrun,
"Stop after parsing, printing, and checking options", 1 },
+ { "child-timeout", o_int, &child_wait,
+ "Number of seconds to wait for child processes at exit" },
+
#ifdef HAVE_MULTILINK
{ "multilink", o_bool, &multilink,
"Enable multilink operation", OPT_PRIO | 1 },
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: pppd.h,v 1.84 2004/10/31 22:23:18 paulus Exp $
+ * $Id: pppd.h,v 1.85 2004/11/04 09:46:50 paulus Exp $
*/
/*
extern char *bundle_name; /* bundle name for multilink */
extern bool dump_options; /* print out option values */
extern bool dryrun; /* check everything, print options, exit */
+extern int child_wait; /* # seconds to wait for children at end */
#ifdef MAXOCTETS
extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */