Detailed usage

Gracefully exit module instances

The process in which the Agent stops a module is not trivial. The EVP Agent first needs to set a status on the module instance that it needs to exit. After some amount of time, if the module did not exit gracefully (by calling exit(3) or returning from main), the agent will forcefully stop and kill the module. This is implemented within the module instance “supervisor”.

All events in a module instance are processed by EVP_processEvent(). If the agent wants the module instance to exit, EVP_processEvent() would still dispatch any pending events. The agent would then notify the module via the event callback when an event is generated by:

EVP_processEvent() would still return EVP_SHOULD_EXIT only if there are no more events pending on the input queue to the module. When any of the *_REASON_EXIT error codes is received, the module instance must stop generating any new events, and keep calling EVP_processEvent() until EVP_SHOULD_EXIT is returned. This is done for the module to be able to process all the pending events before it actually exits. Some examples of functions that generate events are EVP_sendState(), EVP_sendTelemetry() and EVP_sendMessage().

Sample module

A correct implementation of the module would be (includes and some details are omitted for clarity):

static int stopping = 0;

static void
telemetry_cb(EVP_TELEMETRY_CALLBACK_REASON reason, void *userData)
{
        static int counter = 0;
        if (reason == EVP_TELEMETRY_CALLBACK_REASON_EXIT) {
                stopping = 1;
                printf("Telemetry not sent, the module was requested to stop.\n");
        }
        else {
                printf("Telemetry sent %d\n", counter++);
        }
}

int main() {
        struct EVP_telemetry_entry entries[1];
        entries.key = "myKey";
        entries.value = "myValue";

        struct EVP_client *h = EVP_initialize();

        for(;;) {
                // Don't add more event if the module is stopping
                if (!stopping) {
                        EVP_sendTelemetry(h, entries, 1, telemetry_callback, NULL);
                }
                int ret = EVP_processEvent(h, 1000);
                if (ret == EVP_SHOULD_EXIT) {
                        break;
                }
        }

        return 0;
}

When the module instance is requested to stop, EVP_TELEMETRY_CALLBACK_REASON_EXIT is signalled by telemetry_cb, so that the module instance does not call EVP_sendTelemetry() anymore. Then, the module instance flushes all the events in the queue, until EVP_processEvent() returns EVP_SHOULD_EXIT, so the module instance break``s and finally ``return``s from ``main.