diff --git a/include/fluent-bit/flb_input.h b/include/fluent-bit/flb_input.h
index 3e318eb2a32..c94f6d099a6 100644
--- a/include/fluent-bit/flb_input.h
+++ b/include/fluent-bit/flb_input.h
@@ -72,6 +72,9 @@ struct flb_input_plugin {
      */
     int (*cb_ingest) (void *in_context, void *, size_t);
 
+    /* Exit */
+    int (*cb_exit) (void *, struct flb_config *);
+
     /* Input handler configuration */
     void *in_context;
 
@@ -113,5 +116,6 @@ int flb_input_set_collector_event(char *name,
                                   struct flb_config *config);
 void flb_input_initialize_all(struct flb_config *config);
 void flb_input_pre_run_all(struct flb_config *config);
+void flb_input_exit_all(struct flb_config *config);
 
 #endif
diff --git a/include/fluent-bit/flb_output.h b/include/fluent-bit/flb_output.h
index bca096ca1ac..6c8f5508b5d 100644
--- a/include/fluent-bit/flb_output.h
+++ b/include/fluent-bit/flb_output.h
@@ -65,6 +65,9 @@ struct flb_output_plugin {
     /* Flush callback */
     int (*cb_flush) (void *, size_t, void *, struct flb_config *);
 
+    /* Exit */
+    int (*cb_exit) (void *, struct flb_config *);
+
     /* Output handler configuration */
     void *out_context;
 
@@ -80,6 +83,7 @@ struct flb_output_plugin {
 
 int flb_output_set(struct flb_config *config, char *output);
 void flb_output_pre_run(struct flb_config *config);
+void flb_output_exit(struct flb_config *config);
 int flb_output_set_context(char *name, void *out_context, struct flb_config *config);
 int flb_output_init(struct flb_config *config);
 
diff --git a/src/flb_engine.c b/src/flb_engine.c
index 4fe2fd0cb98..77d2a879010 100644
--- a/src/flb_engine.c
+++ b/src/flb_engine.c
@@ -273,6 +273,10 @@ int flb_engine_start(struct flb_config *config)
             if (event->type == FLB_ENGINE_EV_CORE) {
                 ret = flb_engine_handle_event(event->fd, event->mask, config);
                 if (ret == -1) {
+                    /* Inputs exit */
+                    flb_input_exit_all(config);
+                    /* Outputs exit */
+                    flb_output_exit(config);
                     return 0;
                 }
             }
diff --git a/src/flb_input.c b/src/flb_input.c
index a0db0ff0cea..0d634ab7d0c 100644
--- a/src/flb_input.c
+++ b/src/flb_input.c
@@ -91,6 +91,22 @@ void flb_input_pre_run_all(struct flb_config *config)
     }
 }
 
+/* Invoke all exit input callbacks */
+void flb_input_exit_all(struct flb_config *config)
+{
+    struct mk_list *head;
+    struct flb_input_plugin *in;
+
+    mk_list_foreach(head, &config->inputs) {
+        in = mk_list_entry(head, struct flb_input_plugin, _head);
+        if (in->active == FLB_TRUE) {
+            if (in->cb_exit) {
+                in->cb_exit(in->in_context, config);
+            }
+        }
+    }
+}
+
 /* Check that at least one Input is enabled */
 int flb_input_check(struct flb_config *config)
 {
diff --git a/src/flb_output.c b/src/flb_output.c
index 2bb6e9dc87a..201aba62497 100644
--- a/src/flb_output.c
+++ b/src/flb_output.c
@@ -135,6 +135,27 @@ void flb_output_pre_run(struct flb_config *config)
     }
 }
 
+/* Invoke exit call for the output plugin */
+void flb_output_exit(struct flb_config *config)
+{
+    struct mk_list *head;
+    struct flb_output_plugin *out;
+
+    mk_list_foreach(head, &config->outputs) {
+        out = mk_list_entry(head, struct flb_output_plugin, _head);
+        if (out->active == FLB_TRUE) {
+            /* Check a exit callback */
+            if (out->cb_exit) {
+                out->cb_exit(out->out_context, config);
+            }
+
+            if (out->upstream) {
+                /* TODO: close/destroy out->upstream */
+            }
+        }
+    }
+}
+
 /*
  * It validate an output type given the string, it return the
  * proper type and if valid, populate the global config.