From b302749b70bd8b487bdfe0ffcdacbf730da8b6ca Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 13 Apr 2010 09:28:13 -0700 Subject: [PATCH] Make fatal signals cause an exit more promptly in special cases. The fatal-signal library notices and records fatal signals (e.g. SIGTERM) and terminates the process on the next trip through poll_block(). But some special utilities do not always invoke poll_block() promptly, e.g. "ovs-ofctl monitor" does not call poll_block() as long as OpenFlow messages are available. But these special cases seem like they are all likely to call into functions that themselves block (those with "_block" in their names). So make a new rule that such functions should always call fatal_signal_run(), either directly or through poll_block(). This commit implements and documents that rule. Bug #2625. --- lib/fatal-signal.c | 11 +++++++++++ lib/jsonrpc.c | 4 ++++ lib/ovsdb-idl.c | 2 ++ lib/stream.c | 4 ++++ lib/vconn.c | 9 +++++++++ 5 files changed, 30 insertions(+) diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index f6f913ebc..2e38fc51a 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -134,6 +134,17 @@ fatal_signal_handler(int sig_nr) stored_sig_nr = sig_nr; } +/* Check whether a fatal signal has occurred and, if so, call the fatal signal + * hooks and exit. + * + * This function is called automatically by poll_block(), but specialized + * programs that may not always call poll_block() on a regular basis should + * also call it periodically. (Therefore, any function with "block" in its + * name should call fatal_signal_run() each time it is called, either directly + * or through poll_block(), because such functions can only used by specialized + * programs that can afford to block outside their main loop around + * poll_block().) + */ void fatal_signal_run(void) { diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c index 72590a2f4..828bdac21 100644 --- a/lib/jsonrpc.c +++ b/lib/jsonrpc.c @@ -23,6 +23,7 @@ #include "byteq.h" #include "dynamic-string.h" +#include "fatal-signal.h" #include "json.h" #include "list.h" #include "ofpbuf.h" @@ -293,6 +294,8 @@ jsonrpc_send_block(struct jsonrpc *rpc, struct jsonrpc_msg *msg) { int error; + fatal_signal_run(); + error = jsonrpc_send(rpc, msg); if (error) { return error; @@ -314,6 +317,7 @@ jsonrpc_recv_block(struct jsonrpc *rpc, struct jsonrpc_msg **msgp) for (;;) { int error = jsonrpc_recv(rpc, msgp); if (error != EAGAIN) { + fatal_signal_run(); return error; } diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 42c53b831..3f3ce555a 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -25,6 +25,7 @@ #include "bitmap.h" #include "dynamic-string.h" +#include "fatal-signal.h" #include "json.h" #include "jsonrpc.h" #include "ovsdb-data.h" @@ -1281,6 +1282,7 @@ ovsdb_idl_txn_commit_block(struct ovsdb_idl_txn *txn) { enum ovsdb_idl_txn_status status; + fatal_signal_run(); while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) { ovsdb_idl_run(txn->idl); ovsdb_idl_wait(txn->idl); diff --git a/lib/stream.c b/lib/stream.c index 2349b0c11..43b73af0a 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -25,6 +25,7 @@ #include #include "coverage.h" #include "dynamic-string.h" +#include "fatal-signal.h" #include "flow.h" #include "ofp-print.h" #include "ofpbuf.h" @@ -237,6 +238,8 @@ stream_open_block(int error, struct stream **streamp) { struct stream *stream = *streamp; + fatal_signal_run(); + while (error == EAGAIN) { stream_run(stream); stream_run_wait(stream); @@ -570,6 +573,7 @@ pstream_accept_block(struct pstream *pstream, struct stream **new_stream) { int error; + fatal_signal_run(); while ((error = pstream_accept(pstream, new_stream)) == EAGAIN) { pstream_wait(pstream); poll_block(); diff --git a/lib/vconn.c b/lib/vconn.c index d8807fda3..99d5a54d4 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -25,6 +25,7 @@ #include #include "coverage.h" #include "dynamic-string.h" +#include "fatal-signal.h" #include "flow.h" #include "ofp-print.h" #include "ofpbuf.h" @@ -273,6 +274,8 @@ vconn_open_block(const char *name, int min_version, struct vconn **vconnp) struct vconn *vconn; int error; + fatal_signal_run(); + error = vconn_open(name, min_version, &vconn); while (error == EAGAIN) { vconn_run(vconn); @@ -607,6 +610,9 @@ int vconn_send_block(struct vconn *vconn, struct ofpbuf *msg) { int retval; + + fatal_signal_run(); + while ((retval = vconn_send(vconn, msg)) == EAGAIN) { vconn_run(vconn); vconn_run_wait(vconn); @@ -621,6 +627,9 @@ int vconn_recv_block(struct vconn *vconn, struct ofpbuf **msgp) { int retval; + + fatal_signal_run(); + while ((retval = vconn_recv(vconn, msgp)) == EAGAIN) { vconn_run(vconn); vconn_run_wait(vconn); -- 2.39.5