/* ** CM_CLEANUP -- cleanup after interrupt or error. ** ** This routine does things like call the interrupt cleanup ** function, reset the input, etc. ** ** Parameters: ** typ -- the type of cleanup: ** 1 -- fatal error (from error [error.c]). ** 2 -- keyboard interrupt. ** ** Returns: ** never (uses non-local jump to ctlmod/main.c). ** ** Side Effects: ** Proc_name & Cm.cm_input are reset. ** ** Trace Flags: ** 0 */ void cm_cleanup(int typ) { register int i; register func_t *f; extern jmp_buf CmReset; register ctx_t *ctx; #ifdef xCTR2 if (tTf(0, 13)) printf("cm_cleanup: %d\n", typ); #endif /* ** Call all interrupt cleanup functions for active ** modules. */ for (i = 0; i < NumFunc; i++) { f = FuncVect[i]; if (f->fn_active > 0) { setprocname(Ctx.ctx_name = f->fn_name); (*f->fn_cleanup)(typ); } } /* clean up memory */ for (ctx = &Ctx; ctx != NULL; ctx = ctx->ctx_link) { if (ctx->ctx_qt != NULL) { xfree(ctx->ctx_qt); } if (ctx->ctx_glob != NULL) { bmove(ctx->ctx_glob, ctx->ctx_fn->fn_gptr, ctx->ctx_fn->fn_gsize); xfree(ctx->ctx_glob); } } /* return to top of loop */ longjmp(CmReset, typ); }
int probes_init(struct glougloud *ggd) { _ggd = ggd; _probes = xcalloc(1, sizeof(struct glougloud_probes)); _probes->pid = fork(); if (_probes->pid > 0) return 0; setprocname("probes"); droppriv(GLOUGLOUD_USER_PROBES, 1, NULL); _probes->evb = event_base_new(); if (_modules_load() < 0) goto err; _probes->rc = redis_connect(_probes->evb, cb_connect, cb_disconnect); if (_probes->rc->err) return -1; _probes->server = gg_server_start(_probes->evb, &ggd->probes.serv_ip, ggd->probes.serv_port, prb_handle_conn, prb_handle_packet, NULL); if (!_probes->server) { log_warn("probes: gg_server_start failed"); return -1; } event_base_dispatch(_probes->evb); gg_server_stop(_probes->server); return 0; err: probes_shutdown(); return -1; }
int proc_err(pb_t *ppb, int pc, paramv_t *pv) { register func_t *f; register int i; register ctx_t *ctx; #ifdef xCTR2 if (tTf(6, 8)) lprintf("proc_err: new = %d\n", Ctx.ctx_new); #endif pb_prime(ppb, PB_ERR); /* ** Scan back on the list of context dependencies. ** If we come to someone who can process this message, ** we go ahead and do it. We also take this ** opportunity to unwind the context list & call the ** cleanup functions. */ for (ctx = &Ctx; ctx != NULL; ctx = ctx->ctx_link) { setprocname(ctx->ctx_name); f = ctx->ctx_fn; #ifdef xCTR2 if (tTf(6, 9)) lprintf("proc_err: unwinding %s: errfn=%x, ppb=%x, link=%x, resp=%d, fn=%x\n", getprocname(), ctx->ctx_errfn, ctx->ctx_ppb, ctx->ctx_link, ctx->ctx_resp, f); #endif /* Do the actual error processing. */ ppb->pb_proc = ctx->ctx_resp; if (ctx->ctx_errfn != NULL) i = (*ctx->ctx_errfn)(pc, pv); else i = -1; #ifdef xCTR2 if (tTf(6, 11)) lprintf("proc_err: errcode %d\n", i); #endif if (i == 0) break; else if (i > 0) { /* turn into nonfatal error */ ppb->pb_stat |= PB_INFO; ppb->pb_proc = PB_FRONT; } else { /* call the cleanup function */ if (f != NULL && f->fn_active > 0) { (*f->fn_cleanup)(1); } } /* arrange to leave if parent not in this process */ if (ppb->pb_proc != Cm.cm_myproc) { send_off(ppb, pc, pv); pb_flush(ppb); /* throw away dead contexts and exit */ break; } } if (ctx == NULL) { syserr("proc_err: no parent"); } #ifdef xCTR3 MonPpb = getmonppb(); if (tTf(6, 12)) { lprintf("proc_err: cleanup: ctx=%x, ->_link=%x, MonPpb = ", ctx, ctx->ctx_link); pb_dump(MonPpb, TRUE); } #endif /* pop contexts down to ctx and exit */ ctx = ctx->ctx_link; while (Ctx.ctx_link != ctx) { if (Ctx.ctx_link == NULL) syserr("proc_err: underflow"); Ctx.ctx_new = TRUE; resetp(); } /* ** Flush input pipe. ** THIS CODE IS ONLY NEEDED TO MAKE READMON WORK, AND ** SHOULD BE REMOVED WHEN READMON GOES AWAY!! */ if (ctx == NULL) { Cm.cm_input = Cm.cm_rinput; MonPpb = getmonppb(); while (!BITISSET(PB_EOF, MonPpb->pb_stat)) { pb_read(MonPpb); } MonPpb->pb_st = PB_UNKNOWN; } longjmp(Ctx.ctx_jbuf, 1); }