static gboolean afprogram_dd_reopen(AFProgramDestDriver *self) { int fd; if (self->pid != -1) { msg_verbose("Sending destination program a TERM signal", evt_tag_str("cmdline", self->cmdline->str), evt_tag_int("child_pid", self->pid), NULL); kill(self->pid, SIGTERM); self->pid = -1; } msg_verbose("Starting destination program", evt_tag_str("cmdline", self->cmdline->str), NULL); if (!afprogram_popen(self->cmdline->str, G_IO_OUT, &self->pid, &fd)) return FALSE; child_manager_register(self->pid, afprogram_dd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify) log_pipe_unref); g_fd_set_nonblock(fd, TRUE); log_writer_reopen(self->writer, log_proto_text_client_new(log_transport_plain_new(fd, 0))); return TRUE; }
static gboolean afmongodb_dd_init(LogPipe *s) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); ValuePairsTransformSet *vpts; if (!log_dest_driver_init_method(s)) return FALSE; log_template_options_init(&self->template_options, cfg); /* Always replace a leading dot with an underscore. */ vpts = value_pairs_transform_set_new(".*"); value_pairs_transform_set_add_func(vpts, value_pairs_new_transform_replace_prefix(".", "_")); value_pairs_add_transforms(self->vp, vpts); if (self->port != MONGO_CONN_LOCAL) { if (self->address) { gchar *srv = g_strdup_printf ("%s:%d", self->address, (self->port) ? self->port : 27017); self->servers = g_list_prepend (self->servers, srv); g_free (self->address); } if (!self->servers) afmongodb_dd_set_servers((LogDriver *)self, g_list_append (NULL, g_strdup ("127.0.0.1:27017"))); self->address = NULL; self->port = 27017; if (!mongo_util_parse_addr(g_list_nth_data(self->servers, 0), &self->address, &self->port)) { msg_error("Cannot parse the primary host", evt_tag_str("primary", g_list_nth_data(self->servers, 0)), NULL); return FALSE; } } if (self->port == MONGO_CONN_LOCAL) msg_verbose("Initializing MongoDB destination", evt_tag_str("address", self->address), evt_tag_str("database", self->db), evt_tag_str("collection", self->coll), NULL); else msg_verbose("Initializing MongoDB destination", evt_tag_str("address", self->address), evt_tag_int("port", self->port), evt_tag_str("database", self->db), evt_tag_str("collection", self->coll), NULL); return log_threaded_dest_driver_start(s); }
static void detect_local_fqdn_hostname(void) { gchar *hostname; hostname = get_local_hostname_from_system(); if (!is_hostname_fqdn(hostname)) { /* not fully qualified, resolve it using DNS or /etc/hosts */ g_free(hostname); hostname = get_local_fqdn_hostname_from_dns(); if (!hostname) { msg_verbose("Unable to detect fully qualified hostname for localhost, use_fqdn() will use the short hostname", NULL); hostname = get_local_hostname_from_system(); if (!hostname[0]) { msg_error("Could not resolve local hostname either from the DNS nor gethostname(), assuming localhost", NULL); hostname = g_strdup("localhost"); } } } g_strlcpy(local_hostname_fqdn, hostname, sizeof(local_hostname_fqdn)); g_free(hostname); }
gboolean afsocket_dd_deinit(LogPipe *s) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (self->reconnect_timer) g_source_remove(self->reconnect_timer); if (self->source_id && g_source_remove(self->source_id)) { msg_verbose("Closing connecting fd", evt_tag_int("fd", self->fd), NULL); close(self->fd); } if (self->writer) { log_pipe_deinit(self->writer); } if (self->flags & AFSOCKET_KEEP_ALIVE) { cfg_persist_config_add(cfg, afsocket_dd_format_persist_name(self, self->dest_name, FALSE), self->writer, -1, (GDestroyNotify) log_pipe_unref, FALSE); self->writer = NULL; } return TRUE; }
static gboolean afamqp_dd_init(LogPipe *s) { AMQPDestDriver *self = (AMQPDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; if (!self->user || !self->password) { msg_error("Error initializing AMQP destination: username and password MUST be set!", evt_tag_str("driver", self->super.super.super.id), NULL); return FALSE; } log_template_options_init(&self->template_options, cfg); msg_verbose("Initializing AMQP destination", evt_tag_str("vhost", self->vhost), evt_tag_str("host", self->host), evt_tag_int("port", self->port), evt_tag_str("exchange", self->exchange), evt_tag_str("exchange_type", self->exchange_type), NULL); return log_threaded_dest_driver_start(s); }
static gboolean systemd_syslog_sd_acquire_socket(AFSocketSourceDriver *s, gint *acquired_fd) { gint fd, number_of_fds; *acquired_fd = -1; fd = -1; number_of_fds = sd_listen_fds(0); if (number_of_fds > 1) { msg_error("Systemd socket activation failed: got more than one fd", evt_tag_int("number", number_of_fds), NULL); return TRUE; } else if (number_of_fds < 1) { msg_error("Failed to acquire /run/systemd/journal/syslog socket, disabling systemd-syslog source", NULL); return TRUE; } else { fd = SD_LISTEN_FDS_START; msg_debug("Systemd socket activation", evt_tag_int("file-descriptor", fd), NULL); if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, NULL, 0)) { *acquired_fd = fd; } else { msg_error("The systemd supplied UNIX domain socket is of a" " different type, check the configured driver and" " the matching systemd unit file", evt_tag_int("systemd-sock-fd", fd), evt_tag_str("expecting", "unix-dgram()"), NULL); *acquired_fd = -1; return TRUE; } } if (*acquired_fd != -1) { g_fd_set_nonblock(*acquired_fd, TRUE); msg_verbose("Acquired systemd syslog socket", evt_tag_int("systemd-syslog-sock-fd", *acquired_fd), NULL); return TRUE; } return TRUE; }
static gboolean afprogram_sd_deinit(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; if (self->pid != -1) { msg_verbose("Sending source program a TERM signal", evt_tag_str("cmdline", self->cmdline->str), evt_tag_int("child_pid", self->pid), NULL); kill(self->pid, SIGTERM); self->pid = -1; } if (self->reader) { log_pipe_deinit(self->reader); log_pipe_unref(self->reader); self->reader = NULL; } if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; }
/* NOTE: runs in the main thread */ static void affile_sd_notify(LogPipe *s, gint notify_code, gpointer user_data) { AFFileSourceDriver *self = (AFFileSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; switch (notify_code) { case NC_FILE_MOVED: { msg_verbose("Follow-mode file source moved, tracking of the new file is started", evt_tag_str("filename", self->filename->str), NULL); log_pipe_deinit((LogPipe *) self->reader); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; if (affile_sd_open_file(self, self->filename->str, &fd)) { LogProtoServer *proto; PollEvents *poll_events; poll_events = affile_sd_construct_poll_events(self, fd); if (!poll_events) break; proto = affile_sd_construct_proto(self, fd); self->reader = log_reader_new(self->super.super.super.cfg); log_reader_reopen(self->reader, proto, poll_events); log_reader_set_options(self->reader, s, &self->reader_options, STATS_LEVEL1, SCS_FILE, self->super.super.id, self->filename->str); log_reader_set_immediate_check(self->reader); log_pipe_append((LogPipe *) self->reader, s); if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing log_reader, closing fd", evt_tag_int("fd", fd), NULL); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); } affile_sd_recover_state(s, cfg, proto); } break; } default: break; } }
static void afsocket_sd_accept(gpointer s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; GSockAddr *peer_addr; gchar buf1[256], buf2[256]; gint new_fd; gboolean res; int accepts = 0; while (accepts < MAX_ACCEPTS_AT_A_TIME) { GIOStatus status; status = g_accept(self->fd, &new_fd, &peer_addr); if (status == G_IO_STATUS_AGAIN) { /* no more connections to accept */ break; } else if (status != G_IO_STATUS_NORMAL) { msg_error("Error accepting new connection", evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); return; } g_fd_set_nonblock(new_fd, TRUE); g_fd_set_cloexec(new_fd, TRUE); res = afsocket_sd_process_connection(self, peer_addr, self->bind_addr, new_fd); if (res) { if (peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); else msg_verbose("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); } else { close(new_fd); } g_sockaddr_unref(peer_addr); accepts++; } return; }
/* called to apply the new configuration once all I/O worker threads have finished */ static void main_loop_reload_config_apply(void) { if (main_loop_is_terminating()) { if (main_loop_new_config) { cfg_free(main_loop_new_config); main_loop_new_config = NULL; } return; } main_loop_old_config->persist = persist_config_new(); cfg_deinit(main_loop_old_config); cfg_persist_config_move(main_loop_old_config, main_loop_new_config); if (cfg_init(main_loop_new_config)) { msg_verbose("New configuration initialized"); persist_config_free(main_loop_new_config->persist); main_loop_new_config->persist = NULL; cfg_free(main_loop_old_config); current_configuration = main_loop_new_config; service_management_clear_status(); } else { msg_error("Error initializing new configuration, reverting to old config"); service_management_publish_status("Error initializing new configuration, using the old config"); cfg_persist_config_move(main_loop_new_config, main_loop_old_config); cfg_deinit(main_loop_new_config); if (!cfg_init(main_loop_old_config)) { /* hmm. hmmm, error reinitializing old configuration, we're hosed. * Best is to kill ourselves in the hope that the supervisor * restarts us. */ kill(getpid(), SIGQUIT); g_assert_not_reached(); } persist_config_free(main_loop_old_config->persist); main_loop_old_config->persist = NULL; cfg_free(main_loop_new_config); current_configuration = main_loop_old_config; goto finish; } /* this is already running with the new config in place */ app_post_config_loaded(); msg_notice("Configuration reload request received, reloading configuration"); finish: main_loop_new_config = NULL; main_loop_old_config = NULL; return; }
static gboolean afmongodb_dd_connect(MongoDBDestDriver *self, gboolean reconnect) { GList *l; if (reconnect && self->conn) return TRUE; self->conn = mongo_sync_connect(self->host, self->port, FALSE); if (!self->conn) { msg_error ("Error connecting to MongoDB", NULL); return FALSE; } mongo_sync_conn_set_safe_mode(self->conn, self->safe_mode); l = self->servers; while ((l = g_list_next(l)) != NULL) { gchar *host = NULL; gint port = 27017; if (!mongo_util_parse_addr(l->data, &host, &port)) { msg_warning("Cannot parse MongoDB server address, ignoring", evt_tag_str("address", l->data), NULL); continue; } mongo_sync_conn_seed_add (self->conn, host, port); msg_verbose("Added MongoDB server seed", evt_tag_str("host", host), evt_tag_int("port", port), NULL); g_free(host); } /* if (self->user || self->password) { if (!self->user || !self->password) { msg_error("Neither the username, nor the password can be empty", NULL); return FALSE; } if (mongo_cmd_authenticate(&self->mongo_conn, self->db, self->user, self->password) != 1) { msg_error("MongoDB authentication failed", NULL); return FALSE; } } */ return TRUE; }
/* NOTE: runs in the main thread */ static void affile_sd_notify(LogPipe *s, LogPipe *sender, gint notify_code, gpointer user_data) { AFFileSourceDriver *self = (AFFileSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; switch (notify_code) { case NC_FILE_MOVED: { msg_verbose("Follow-mode file source moved, tracking of the new file is started", evt_tag_str("filename", self->filename->str), NULL); log_pipe_deinit(self->reader); log_pipe_unref(self->reader); if (affile_sd_open_file(self, self->filename->str, &fd)) { LogTransport *transport; LogProto *proto; transport = log_transport_plain_new(fd, 0); transport->timeout = 10; proto = affile_sd_construct_proto(self, transport); self->reader = log_reader_new(proto); log_reader_set_options(self->reader, s, &self->reader_options, 1, SCS_FILE, self->super.super.id, self->filename->str); log_reader_set_follow_filename(self->reader, self->filename->str); log_reader_set_immediate_check(self->reader); log_pipe_append(self->reader, s); if (!log_pipe_init(self->reader, cfg)) { msg_error("Error initializing log_reader, closing fd", evt_tag_int("fd", fd), NULL); log_pipe_unref(self->reader); self->reader = NULL; close(fd); } affile_sd_recover_state(s, cfg, proto); } else { self->reader = NULL; } break; } default: break; } }
gboolean afsocket_sd_deinit(LogPipe *s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if ((self->flags & AFSOCKET_KEEP_ALIVE) == 0 || !cfg->persist) { afsocket_sd_kill_connection_list(self->connections); } else { GList *p; /* for AFSOCKET_STREAM source drivers this is a list, for * AFSOCKET_DGRAM this is a single connection */ for (p = self->connections; p; p = p->next) { log_pipe_deinit((LogPipe *) p->data); } cfg_persist_config_add(cfg, afsocket_sd_format_persist_name(self, FALSE), self->connections, (GDestroyNotify) afsocket_sd_kill_connection_list, FALSE); } self->connections = NULL; if (self->flags & AFSOCKET_STREAM) { afsocket_sd_stop_watches(self); if ((self->flags & AFSOCKET_KEEP_ALIVE) == 0) { msg_verbose("Closing listener fd", evt_tag_int("fd", self->fd), NULL); close(self->fd); } else { /* NOTE: the fd is incremented by one when added to persistent config * as persist config cannot store NULL */ cfg_persist_config_add(cfg, afsocket_sd_format_persist_name(self, TRUE), GUINT_TO_POINTER(self->fd + 1), afsocket_sd_close_fd, FALSE); } } else if (self->flags & AFSOCKET_DGRAM) { /* we don't need to close the listening fd here as we have a * single connection which will close it */ ; } if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; }
static inline void _terminate_process_group_by_pid(const pid_t pid) { msg_verbose("Sending TERM signal to the process group", evt_tag_int("pid", pid)); pid_t pgid = getpgid(pid); if (pgid != -1 && pgid != getpgrp()) killpg(pgid, SIGTERM); }
static LogProtoStatus log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_read) { gint rc; if (self->buffer_pos == self->buffer_end) self->buffer_pos = self->buffer_end = 0; if (self->buffer_size == self->buffer_end) { /* no more space in the buffer, we can't fetch further data. Move the * things we already have to the beginning of the buffer to make * space. */ memmove(self->buffer, &self->buffer[self->buffer_pos], self->buffer_end - self->buffer_pos); self->buffer_end = self->buffer_end - self->buffer_pos; self->buffer_pos = 0; } if (!(*may_read)) return LPS_SUCCESS; rc = log_transport_read(self->super.transport, &self->buffer[self->buffer_end], self->buffer_size - self->buffer_end, NULL); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error reading RFC5428 style framed data", evt_tag_int("fd", self->super.transport->fd), evt_tag_errno("error", errno), NULL); return LPS_ERROR; } else { /* we need more data to parse this message but the data is not available yet */ self->half_message_in_buffer = TRUE; } } else if (rc == 0) { msg_verbose("EOF occurred while reading", evt_tag_int(EVT_TAG_FD, self->super.transport->fd), NULL); return LPS_EOF; } else { self->buffer_end += rc; } return LPS_SUCCESS; }
void log_transport_free_method(LogTransport *s) { if (s->fd != -1) { msg_verbose("Closing log transport fd", evt_tag_int("fd", s->fd), NULL); close(s->fd); } }
static void afprogram_dd_kill_child(AFProgramDestDriver *self) { if (self->process_info.pid != -1) { msg_verbose("Sending destination program a TERM signal", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("child_pid", self->process_info.pid)); _terminate_process_group_by_pid(self->process_info.pid); self->process_info.pid = -1; } }
static gboolean afmongodb_dd_init(LogPipe *s) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; if (cfg) self->time_reopen = cfg->time_reopen; if (!self->vp) { self->vp = value_pairs_new(); value_pairs_add_scope(self->vp, "selected-macros"); value_pairs_add_scope(self->vp, "nv-pairs"); } self->host = NULL; self->port = 27017; if (!mongo_util_parse_addr(g_list_nth_data(self->servers, 0), &self->host, &self->port)) { msg_error("Cannot parse the primary host", evt_tag_str("primary", g_list_nth_data(self->servers, 0)), NULL); return FALSE; } msg_verbose("Initializing MongoDB destination", evt_tag_str("host", self->host), evt_tag_int("port", self->port), evt_tag_str("database", self->db), evt_tag_str("collection", self->coll), NULL); self->queue = log_dest_driver_acquire_queue(&self->super, afmongodb_dd_format_persist_name(self)); stats_lock(); stats_register_counter(0, SCS_MONGODB | SCS_DESTINATION, self->super.super.id, afmongodb_dd_format_stats_instance(self), SC_TYPE_STORED, &self->stored_messages); stats_register_counter(0, SCS_MONGODB | SCS_DESTINATION, self->super.super.id, afmongodb_dd_format_stats_instance(self), SC_TYPE_DROPPED, &self->dropped_messages); stats_unlock(); log_queue_set_counters(self->queue, self->stored_messages, self->dropped_messages); afmongodb_dd_start_thread(self); return TRUE; }
static gboolean afprogram_sd_init(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; if (!log_src_driver_init_method(s)) return FALSE; if (cfg) log_reader_options_init(&self->reader_options, cfg, self->super.super.group); msg_verbose("Starting source program", evt_tag_str("cmdline", self->process_info.cmdline->str)); if (!afprogram_popen(&self->process_info, G_IO_IN, &fd)) return FALSE; /* parent */ child_manager_register(self->process_info.pid, afprogram_sd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify) log_pipe_unref); g_fd_set_nonblock(fd, TRUE); g_fd_set_cloexec(fd, TRUE); if (!self->reader) { LogTransport *transport; transport = log_transport_pipe_new(fd); self->reader = log_reader_new(s->cfg); log_reader_reopen(self->reader, log_proto_text_server_new(transport, &self->reader_options.proto_options.super), poll_fd_events_new(fd)); log_reader_set_options(self->reader, s, &self->reader_options, STATS_LEVEL0, SCS_PROGRAM, self->super.super.id, self->process_info.cmdline->str); } log_pipe_append((LogPipe *) self->reader, &self->super.super.super); if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing program source, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } return TRUE; }
static void afprogram_sd_kill_child(AFProgramSourceDriver *self) { if (self->pid != -1) { msg_verbose("Sending source program a TERM signal", evt_tag_str("cmdline", self->cmdline->str), evt_tag_int("child_pid", self->pid), NULL); _terminate_process_group_by_pid(self->pid); self->pid = -1; } }
void log_transport_free_method(LogTransport *s) { if (((s->flags & LTF_DONTCLOSE) == 0) && s->fd != -1) { msg_verbose("Closing log transport fd", evt_tag_int("fd", s->fd), NULL); if (s->flags & LTF_SHUTDOWN) shutdown(s->fd, SHUT_RDWR); close(s->fd); } }
static void afprogram_dd_kill_child(AFProgramDestDriver *self) { if (self->pid != -1) { msg_verbose("Sending destination program a TERM signal", evt_tag_str("cmdline", self->cmdline->str), evt_tag_int("child_pid", self->pid), NULL); kill(-self->pid, SIGTERM); self->pid = -1; } }
static void afprogram_sd_exit(pid_t pid, int status, gpointer s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; /* Note: self->process_info.pid being -1 means that deinit was called, thus we don't * need to restart the command. self->process_info.pid might change due to EPIPE * handling restarting the command before this handler is run. */ if (self->process_info.pid != -1 && self->process_info.pid == pid) { msg_verbose("Child program exited", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("status", status)); self->process_info.pid = -1; } }
static void afsocket_dd_stop_watches(AFSocketDestDriver *self) { main_loop_assert_main_thread(); if (iv_fd_registered(&self->connect_fd)) { iv_fd_unregister(&self->connect_fd); /* need to close the fd in this case as it wasn't established yet */ msg_verbose("Closing connecting fd", evt_tag_int("fd", self->fd)); close(self->fd); } if (iv_timer_registered(&self->reconnect_timer)) iv_timer_unregister(&self->reconnect_timer); }
static gboolean afprogram_dd_deinit(LogPipe *s, GlobalConfig *cfg, PersistentConfig *persist) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; if (self->pid != -1) { msg_verbose("Sending child a TERM signal", evt_tag_int("child_pid", self->pid), NULL); kill(self->pid, SIGTERM); self->pid = -1; } if (self->writer) log_pipe_deinit(self->writer, NULL, NULL); return TRUE; }
static gboolean afamqp_dd_init(LogPipe *s) { AMQPDestDriver *self = (AMQPDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; if (cfg) self->time_reopen = cfg->time_reopen; if (!self->vp) { self->vp = value_pairs_new(); value_pairs_add_scope(self->vp, "selected-macros"); value_pairs_add_scope(self->vp, "nv-pairs"); value_pairs_add_scope(self->vp, "sdata"); } msg_verbose("Initializing AMQP destination", evt_tag_str("vhost", self->vhost), evt_tag_str("host", self->host), evt_tag_int("port", self->port), evt_tag_str("exchange", self->exchange), evt_tag_str("exchange_type", self->exchange_type), NULL); self->queue = log_dest_driver_acquire_queue(&self->super, afamqp_dd_format_persist_name(self)); stats_lock(); stats_register_counter(0, SCS_AMQP | SCS_DESTINATION, self->super.super.id, afamqp_dd_format_stats_instance(self), SC_TYPE_STORED, &self->stored_messages); stats_register_counter(0, SCS_AMQP | SCS_DESTINATION, self->super.super.id, afamqp_dd_format_stats_instance(self), SC_TYPE_DROPPED, &self->dropped_messages); stats_unlock(); log_queue_set_counters(self->queue, self->stored_messages, self->dropped_messages); afamqp_dd_start_thread(self); return TRUE; }
static gboolean afprogram_dd_reopen(AFProgramDestDriver *self) { int fd; afprogram_dd_kill_child(self); msg_verbose("Starting destination program", evt_tag_str("cmdline", self->cmdline->str), NULL); if (!afprogram_popen(self->cmdline->str, G_IO_OUT, &self->pid, &fd)) return FALSE; child_manager_register(self->pid, afprogram_dd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify) log_pipe_unref); g_fd_set_nonblock(fd, TRUE); log_writer_reopen(self->writer, log_proto_text_client_new(log_transport_pipe_new(fd), &self->writer_options.proto_options.super)); return TRUE; }
static gboolean redis_dd_init(LogPipe *s) { RedisDriver *self = (RedisDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; log_template_options_init(&self->template_options, cfg); msg_verbose("Initializing Redis destination", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("host", self->host), evt_tag_int("port", self->port), NULL); return log_threaded_dest_driver_start(s); }
static inline gboolean afprogram_dd_open_program(AFProgramDestDriver *self, int *fd) { if (self->process_info.pid == -1) { msg_verbose("Starting destination program", evt_tag_str("cmdline", self->process_info.cmdline->str)); if (!afprogram_popen(&self->process_info, G_IO_OUT, fd)) return FALSE; g_fd_set_nonblock(*fd, TRUE); } child_manager_register(self->process_info.pid, afprogram_dd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify)log_pipe_unref); return TRUE; }
static void afprogram_dd_exit(pid_t pid, int status, gpointer s) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; /* Note: self->pid being -1 means that deinit was called, thus we don't * need to restart the command. self->pid might change due to EPIPE * handling restarting the command before this handler is run. */ if (self->pid != -1 && self->pid == pid) { msg_verbose("Child program exited, restarting", evt_tag_str("cmdline", self->cmdline->str), evt_tag_int("status", status), NULL); self->pid = -1; log_pipe_deinit(&self->super.super, NULL, NULL); log_pipe_init(&self->super.super, NULL, NULL); } }