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); }
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); }
bool master_udp::run_alone(const char* addrs, const char* path /* = NULL */, unsigned int count /* = 1 */) { // 每个进程只能有一个实例在运行 acl_assert(has_called == false); has_called = true; daemon_mode_ = false; __count_limit = count; acl_assert(addrs && *addrs); #ifdef ACL_WINDOWS acl_init(); #endif ACL_EVENT* eventp = acl_event_new_select(1, 0); set_event(eventp); // 设置基类的事件句柄 ACL_ARGV* tokens = acl_argv_split(addrs, ";,| \t"); ACL_ITER iter; acl_foreach(iter, tokens) { const char* addr = (const char*) iter.data; ACL_VSTREAM* sstream = acl_vstream_bind(addr, 0); if (sstream == NULL) { logger_error("bind %s error %s", addr, last_serror()); close_sstreams(); acl_event_free(eventp); acl_argv_free(tokens); return false; } acl_event_enable_read(eventp, sstream, 0, read_callback, sstream); socket_stream* ss = NEW socket_stream(); if (ss->open(sstream) == false) logger_fatal("open stream error!"); sstream->context = ss; sstreams_.push_back(ss); } acl_argv_free(tokens); // 初始化配置参数 conf_.load(path); service_pre_jail(NULL, NULL); service_init(NULL, NULL); while (!__stop) acl_event_loop(eventp); service_exit(NULL, NULL); // 必须在调用 acl_event_free 前调用 close_sstreams,因为在关闭 // 网络流对象时依然有对 ACL_EVENT 引擎的使用 close_sstreams(); acl_event_free(eventp); return true; }
static void read_fn(int event_type acl_unused, void *context) { EVENT_DOG *evdog = (EVENT_DOG*) context; char buf[2]; evdog->client->rw_timeout = 1; if (acl_vstream_readn(evdog->client, buf, 1) == ACL_VSTREAM_EOF) { acl_event_disable_read(evdog->eventp, evdog->client); event_dog_reopen(evdog); } else acl_event_enable_read(evdog->eventp, evdog->client, 0, read_fn, evdog); }
static void run(ACL_EVENT* event) { acl::socket_stream udp; // 绑定本地地址 if (udp.bind_udp(__local_addr) == false) { printf("bind addr %s error %s\r\n", __server_addr, acl::last_serror()); return; } // 设置远程服务地址 else udp.set_peer(__server_addr); udp.set_rw_timeout(100); ACL_VSTREAM* udp_stream = udp.get_vstream(); acl::socket_stream stdio_in; stdio_in.open(0); ACL_VSTREAM* in = stdio_in.get_vstream(); acl::socket_stream out; out.open(2); udp.set_tcp_non_blocking(true); stdio_in.set_tcp_non_blocking(true); acl_event_enable_read(event, in, 0, stdin_read_callback, &udp); acl_event_enable_read(event, udp_stream, 0, udp_read_callback, &out); out.write("Escape character is '^]'.\r\n"); while (true) { acl_event_loop(event); } }
static void http_server(ACL_VSTREAM *cstream) { ACL_EVENT *event = (ACL_EVENT *) cstream->context; acl::socket_stream conn; conn.open(cstream); acl::memcache_session session("127.0.0.1:11211"); http_servlet servlet(&conn, &session); servlet.setLocalCharset("gb2312"); if (servlet.doRun() == false) return; conn.unbind(); acl_event_enable_read(event, cstream, 120, client_callback, NULL); }
static void read_fn(int event_type acl_unused, ACL_EVENT *event, ACL_VSTREAM *stream, void *context) { const char *myname = "read_fn"; EVENT_DOG *evdog = (EVENT_DOG*) context; char buf[2]; if (evdog->client != stream) acl_msg_fatal("%s(%d), %s: stream != evdog->client", __FILE__, __LINE__, myname); evdog->client->rw_timeout = 1; if (acl_vstream_readn(evdog->client, buf, 1) == ACL_VSTREAM_EOF) { acl_event_disable_read(event, stream); event_dog_reopen(evdog); } else acl_event_enable_read(event, stream, 0, read_fn, evdog); }
static void echo_client(ACL_VSTREAM *cstream) { ACL_EVENT *event = (ACL_EVENT *) cstream->context; const char* res = "HTTP/1.1 200 OK\r\n" "Date: Tue, 31 May 2016 14:20:28 GMT\r\n" "Server: acl\r\n" "Content-Type: text/html\r\n" "Content-Length: 12\r\n" "Connection: Keep-Alive\r\n" "\r\n" "hello world!"; size_t len = strlen(res); if (http_demo(cstream, res, len) < 0 || __stop) acl_vstream_close(cstream); else acl_event_enable_read(event, cstream, 120, client_callback, NULL); }
static void event_dog_open(EVENT_DOG *evdog) { const char *myname = "event_dog_open"; const char *addr = "127.0.0.1:0"; char ebuf[256]; evdog->sstream = acl_vstream_listen(addr, 32); if (evdog->sstream == NULL) acl_msg_fatal("%s(%d): listen on addr(%s) error(%s)", myname, __LINE__, addr, acl_last_strerror(ebuf, sizeof(ebuf))); evdog->server = acl_vstream_connect(evdog->sstream->local_addr, ACL_BLOCKING, 0, 0, 1024); if (evdog->server == NULL) acl_msg_fatal("%s(%d): connect to addr(%s) error(%s)", myname, __LINE__, addr, acl_last_strerror(ebuf, sizeof(ebuf))); if (acl_vstream_writen(evdog->server, ebuf, 1) == ACL_VSTREAM_EOF) acl_msg_fatal("%s(%d): pre write error(%s)", myname, __LINE__, acl_last_strerror(ebuf, sizeof(ebuf))); evdog->client = acl_vstream_accept(evdog->sstream, ebuf, sizeof(ebuf)); if (evdog->client == NULL) acl_msg_fatal("%s(%d): accept error(%s)", myname, __LINE__, acl_last_strerror(ebuf, sizeof(ebuf))); if (acl_vstream_readn(evdog->client, ebuf, 1) == ACL_VSTREAM_EOF) acl_msg_fatal("%s(%d): pre read error(%s)", myname, __LINE__, acl_last_strerror(ebuf, sizeof(ebuf))); acl_vstream_close(evdog->sstream); evdog->sstream = NULL; acl_event_enable_read(evdog->eventp, evdog->client, 0, read_fn, evdog); }
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)); }