void acl_master_status_init(ACL_MASTER_SERV *serv) { const char *myname = "acl_master_status_init"; /* * Sanity checks. */ if (serv->status_fd[0] >= 0 || serv->status_fd[1] >= 0) acl_msg_panic("%s: status events already enabled", myname); if (acl_msg_verbose) acl_msg_info("%s: %s", myname, serv->name); /* * Make the read end of this service's status pipe non-blocking so that * we can detect partial writes on the child side. We use a duplex pipe * so that the child side becomes readable when the master goes away. */ if (acl_duplex_pipe(serv->status_fd) < 0) acl_msg_fatal("pipe: %s", strerror(errno)); acl_non_blocking(serv->status_fd[0], ACL_BLOCKING); acl_close_on_exec(serv->status_fd[0], ACL_CLOSE_ON_EXEC); acl_close_on_exec(serv->status_fd[1], ACL_CLOSE_ON_EXEC); serv->status_read_stream = acl_vstream_fdopen(serv->status_fd[0], O_RDWR, acl_var_master_buf_size, acl_var_master_rw_timeout, ACL_VSTREAM_TYPE_SOCK); if (acl_msg_verbose) acl_msg_info("%s(%d)->%s: call acl_event_enable_read, " "status_fd = %d", __FILE__, __LINE__, myname, serv->status_fd[0]); acl_event_enable_read(acl_var_master_global_event, serv->status_read_stream, 0, master_status_event, (void *) serv); }
void acl_master_flow_init(void) { char *myname = "acl_master_flow_init"; if (pipe(acl_var_master_flow_pipe) < 0) acl_msg_fatal("%s(%d)->%s: pipe: %s", __FILE__, __LINE__, myname, strerror(errno)); acl_non_blocking(acl_var_master_flow_pipe[0], ACL_NON_BLOCKING); acl_non_blocking(acl_var_master_flow_pipe[1], ACL_NON_BLOCKING); acl_close_on_exec(acl_var_master_flow_pipe[0], ACL_CLOSE_ON_EXEC); acl_close_on_exec(acl_var_master_flow_pipe[1], ACL_CLOSE_ON_EXEC); }
int acl_unix_trigger(ACL_EVENT *event, const char *service, const char *buf, int len, int timeout) { const char *myname = "acl_unix_trigger"; struct ACL_UNIX_TRIGGER *up; ACL_SOCKET fd; if (acl_msg_verbose > 0) acl_msg_info("%s: service %s", myname, service); /* * Connect... */ if ((fd = acl_unix_connect(service, ACL_BLOCKING, timeout)) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: connect to %s: %s", myname, service, strerror(errno)); return -1; } acl_close_on_exec(fd, ACL_CLOSE_ON_EXEC); /* * Stash away context. */ up = (struct ACL_UNIX_TRIGGER *) acl_mymalloc(sizeof(*up)); up->service = acl_mystrdup(service); up->stream = acl_vstream_fdopen(fd, O_RDWR, 4096, timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX); /* * Write the request... */ if (acl_vstream_writen(up->stream, buf, len) < 0 || acl_vstream_writen(up->stream, "", 1) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: write to %s: %s", myname, service, strerror(errno)); } /* * Wakeup when the peer disconnects, or when we lose patience. */ #ifdef __USE_TIMER if (timeout > 0) acl_event_request_timer(event, acl_unix_trigger_timer, (void *) up, (timeout + 100) * 1000000); acl_event_enable_read(event, up->stream, 0, acl_unix_trigger_event, (void *) up); #else if (timeout > 0) acl_event_enable_read(event, up->stream, timeout + 100, acl_unix_trigger_event, (void *) up); else acl_event_enable_read(event, up->stream, 0, acl_unix_trigger_event, (void *) up); #endif return 0; }
int acl_inet_trigger(ACL_EVENT *eventp, const char *service, const char *buf, int len, int timeout) { const char *myname = "acl_inet_trigger"; struct ACL_INET_TRIGGER *ip; int fd; if (acl_msg_verbose > 1) acl_msg_info("%s: service %s", myname, service); /* * Connect... */ if ((fd = acl_inet_connect(service, ACL_BLOCKING, timeout)) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: connect to %s: %s", myname, service, strerror(errno)); return (-1); } acl_close_on_exec(fd, ACL_CLOSE_ON_EXEC); /* * Stash away context. */ ip = (struct ACL_INET_TRIGGER *) acl_mymalloc(sizeof(*ip)); ip->fd = fd; ip->service = acl_mystrdup(service); ip->stream = acl_vstream_fdopen(fd, O_RDWR, 4096, timeout, ACL_VSTREAM_TYPE_LISTEN_INET); ip->eventp = eventp; /* * Write the request... */ if (acl_write_buf(fd, buf, len, timeout) < 0 || acl_write_buf(fd, "", 1, timeout) < 0) { if (acl_msg_verbose) acl_msg_warn("%s: write to %s: %s", myname, service, strerror(errno)); } /* * Wakeup when the peer disconnects, or when we lose patience. */ if (timeout > 0) acl_event_enable_read(ip->eventp, ip->stream, timeout + 100, acl_inet_trigger_event, (void *) ip); else acl_event_enable_read(ip->eventp, ip->stream, 0, acl_inet_trigger_event, (void *) ip); return (0); }
static void notify_thread(void *arg) { const char *myname = "notify_thread"; WARN_INFO *info = (WARN_INFO*) arg; ACL_VSTREAM *client; ACL_VSTRING *buf; int ret; buf = acl_vstring_alloc(256); acl_vstring_sprintf(buf, "PROC=%s|PID=%d|RCPT=%s|info=%s\r\n", info->path, info->pid, info->notify_recipients, info->desc); client = acl_vstream_connect(info->notify_addr, ACL_BLOCKING, 60, 60, 1024); if (client == NULL) { acl_msg_error("%s(%d): connect %s error, info(%s)", myname, __LINE__, info->notify_addr, acl_vstring_str(buf)); acl_vstring_free(buf); warn_info_free(info); return; } /* 禁止将该句柄传递给子进程 */ acl_close_on_exec(ACL_VSTREAM_SOCK(client), ACL_CLOSE_ON_EXEC); ret = acl_vstream_writen(client, acl_vstring_str(buf), ACL_VSTRING_LEN(buf)); if (ret == ACL_VSTREAM_EOF) acl_msg_error("%s(%d): write to notify server error, info(%s)", myname, __LINE__, acl_vstring_str(buf)); else acl_msg_info("%s(%d): notify ok!", myname, __LINE__); acl_vstream_close(client); acl_vstring_free(buf); warn_info_free(info); }
void acl_master_sigsetup(void) { char *myname = "acl_master_sigsetup"; struct sigaction action; static int sigs[] = { SIGINT, SIGQUIT, SIGILL, SIGBUS, /* SIGSEGV, only for test */ SIGTERM, }; unsigned i; sigemptyset(&action.sa_mask); action.sa_flags = 0; /* * Prepare to kill our children * when we receive any of the above signals. */ action.sa_handler = master_sigdeath; for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0) acl_msg_fatal("%s: sigaction(%d): %s", myname, sigs[i], strerror(errno)); #ifdef USE_SIG_PIPE if (pipe(acl_master_sig_pipe)) acl_msg_fatal("pipe: %s", strerror(errno)); acl_non_blocking(ACL_SIG_PIPE_WRITE_FD, ACL_NON_BLOCKING); acl_non_blocking(ACL_SIG_PIPE_READ_FD, ACL_NON_BLOCKING); acl_close_on_exec(ACL_SIG_PIPE_WRITE_FD, ACL_CLOSE_ON_EXEC); acl_close_on_exec(ACL_SIG_PIPE_READ_FD, ACL_CLOSE_ON_EXEC); ACL_SIG_PIPE_READ_STREAM = acl_vstream_fdopen(ACL_SIG_PIPE_READ_FD, O_RDONLY, acl_var_master_buf_size, acl_var_master_rw_timeout, ACL_VSTREAM_TYPE_SOCK); if (ACL_SIG_PIPE_READ_STREAM == NULL) acl_msg_fatal("%s(%d)->%s: acl_vstream_fdopen error=%s", __FILE__, __LINE__, myname, strerror(errno)); if (acl_msg_verbose) acl_msg_info("%s(%d)->%s: call acl_event_enable_read, " "SIG_PIPE_READ_FD = %d", __FILE__, __LINE__, myname, ACL_SIG_PIPE_READ_FD); acl_event_enable_read(acl_var_master_global_event, ACL_SIG_PIPE_READ_STREAM, 0, master_sig_event, (void *) 0); #endif /* * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit). */ #ifdef SA_RESTART action.sa_flags |= SA_RESTART; #endif action.sa_handler = master_sighup; if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0) acl_msg_fatal("%s: sigaction(%d): %s", myname, SIGHUP, strerror(errno)); action.sa_flags |= SA_NOCLDSTOP; action.sa_handler = master_sigchld; if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0) acl_msg_fatal("%s: sigaction(%d): %s", myname, SIGCHLD, strerror(errno)); }