diff --git a/lib/hcl-x.h b/lib/hcl-x.h index d3c241e..7e2464e 100644 --- a/lib/hcl-x.h +++ b/lib/hcl-x.h @@ -487,13 +487,24 @@ HCL_EXPORT int hcl_sys_send_iov ( ); HCL_EXPORT int hcl_sys_open_pipes ( - int pfd[2] + int pfd[2], + int nonblock ); HCL_EXPORT void hcl_sys_close_pipes ( int pfd[2] ); +HCL_EXPORT int hcl_sys_set_nonblock ( + int fd, + int v +); + +HCL_EXPORT int hcl_sys_set_cloexec ( + int fd, + int v +); + #if defined(__cplusplus) } #endif diff --git a/lib/x-client.c b/lib/x-client.c index 25c9556..d78aa19 100644 --- a/lib/x-client.c +++ b/lib/x-client.c @@ -159,7 +159,7 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p return HCL_NULL; } - if (hcl_sys_open_pipes(pfd) <= -1) + if (hcl_sys_open_pipes(pfd, 1) <= -1) { if (errnum) *errnum = hcl->vmprim.syserrstrb(hcl, 0, errno, HCL_NULL, 0); goto oops; @@ -440,6 +440,8 @@ static int client_connect (hcl_client_t* client, const char* ipaddr, int reuse_a goto oops; } + hcl_sys_set_cloexec(sck, 1); + if (reuse_addr) { if (sckfam == AF_INET) @@ -481,6 +483,7 @@ static int client_connect (hcl_client_t* client, const char* ipaddr, int reuse_a goto oops; } + hcl_sys_set_nonblock(sck, 1); /* make it nonblocking after connection has been established */ memset (&proto, 0, HCL_SIZEOF(proto_cb)); proto_cb.on_packet = client->prim.on_packet; @@ -639,9 +642,11 @@ static int on_control_event (hcl_client_t* client, struct pollfd* pfd) } + static int on_server_event (hcl_client_t* client, struct pollfd* pfd, int shut_wr_after_req) { +#if 0 if (pfd->revents & POLLERR) { hcl_client_seterrbfmt (client, HCL_ESYSERR, "error condition detected on %d", client->sck); @@ -737,6 +742,7 @@ carry_on: } if (hcl_xproto_geteof(client->proto)) break; +#endif } static int on_script_event (hcl_client_t* client, struct pollfd* pfd) @@ -744,7 +750,7 @@ static int on_script_event (hcl_client_t* client, struct pollfd* pfd) ssize_t n; hcl_uint8_t buf[128]; - n = read(pfd.fd, buf, HCL_SIZEOF(buf)); + n = read(pfd->fd, buf, HCL_SIZEOF(buf)); if (n <= -1) { } @@ -759,15 +765,20 @@ static int on_script_event (hcl_client_t* client, struct pollfd* pfd) int hcl_client_start (hcl_client_t* client, const char* ipaddr, const char* script, int reuse_addr, int shut_wr_after_req) { const char* scptr, * sccur; - int script_fd = STDIN_FILENO; + int cin = STDIN_FILENO; + int cout = STDOUT_FILENO; + int cerr = STDERR_FILENO; - if (client_connect(client, ipaddr, reuse_addr) <= -1) return -1; + /* TODO: cin, cout, cerr could be actual files or something other than the console. + the actual loop won't begin until all these file descriptors are ready */ + + if (client_connect(client, ipaddr, reuse_addr) <= -1) return -1; /* TODO: support time out or abort while connecting... */ scptr = sccur = script; while (1) { ssize_t n, i; - struct pollfd pfd[3]; + struct pollfd pfd[5]; n = 0; @@ -780,9 +791,9 @@ int hcl_client_start (hcl_client_t* client, const char* ipaddr, const char* scri if (*sccur != '\0') pfd[n].events |= POLLOUT; pfd[n++].revents = 0; - if (script_fd >= 0) + if (cin >= 0) { - pfd[n].fd = script_fd; + pfd[n].fd = cin; pfd[n].events = POLLIN; pfd[n++].revents = 0; } @@ -812,7 +823,7 @@ int hcl_client_start (hcl_client_t* client, const char* ipaddr, const char* scri /* event from the server */ on_server_event (client, &pfd[i], shut_wr_after_req); } - else if (pfd[i].fd == script_fd) + else if (pfd[i].fd == cin) { on_script_event (client, &pfd[i]); } diff --git a/lib/x-server.c b/lib/x-server.c index 0b522c4..cbb2eab 100644 --- a/lib/x-server.c +++ b/lib/x-server.c @@ -1086,7 +1086,7 @@ hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_p goto oops; } - if (hcl_sys_open_pipes(pfd) <= -1) + if (hcl_sys_open_pipes(pfd, 1) <= -1) { if (errnum) *errnum = hcl->vmprim.syserrstrb(hcl, 0, errno, HCL_NULL, 0); goto oops; @@ -1782,21 +1782,8 @@ static int setup_listeners (hcl_server_t* server, const hcl_bch_t* addrs) optval = 1; setsockopt (srv_fd, SOL_SOCKET, SO_REUSEADDR, &optval, HCL_SIZEOF(int)); - - #if defined(O_NONBLOCK) || defined(O_CLOEXEC) - fcv = fcntl(srv_fd, F_GETFD, 0); - if (fcv >= 0) - { - #if defined(O_NONBLOCK) - fcv |= O_NONBLOCK; - #endif - #if defined(O_CLOEXEC) - fcv |= O_CLOEXEC; - #endif - - fcntl(srv_fd, F_SETFL, fcv); - } - #endif + hcl_sys_set_nonblock (srv_fd, 1); + hcl_sys_set_cloexec (srv_fd, 1); if (bind(srv_fd, (struct sockaddr*)&srv_addr, srv_len) == -1) { @@ -1936,19 +1923,8 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs) break; } - #if defined(O_NONBLOCK) || defined(O_CLOEXEC) - fcv = fcntl(cli_fd, F_GETFD, 0); - if (fcv >= 0) - { - #if defined(O_NONBLOCK) - fcv &= ~O_NONBLOCK; // force the accepted socket to be blocking - #endif - #if defined(O_CLOEXEC) - fcv |= O_CLOEXEC; - #endif - fcntl(cli_fd, F_SETFD, fcv); - } - #endif + hcl_sys_set_nonblock (cli_fd, 0); /* force the accepted socket to be blocking */ + hcl_sys_set_cloexec (cli_fd, 1); if (server->cfg.worker_max_count > 0) { @@ -2242,37 +2218,16 @@ int hcl_sys_send_iov (int sck, hcl_iovec_t* iov, int count) return 0; } -int hcl_sys_open_pipes (int pfd[2]) +int hcl_sys_open_pipes (int pfd[2], int nonblock) { - int fcv; + /* TODO: mimic open_pipes() in std.c */ if (pipe(pfd) <= -1) return -1; -#if defined(O_NONBLOCK) || defined(O_CLOEXEC) - fcv = fcntl(pfd[0], F_GETFD, 0); - if (fcv >= 0) - { - #if defined(O_NONBLOCK) - fcv |= O_NONBLOCK; - #endif - #if defined(O_CLOEXEC) - fcv |= O_CLOEXEC; - #endif - fcntl(pfd[0], F_SETFD, fcv); - } - - fcv = fcntl(pfd[1], F_GETFD, 0); - if (fcv >= 0) - { - #if defined(O_NONBLOCK) - fcv |= O_NONBLOCK; - #endif - #if defined(O_CLOEXEC) - fcv |= O_CLOEXEC; - #endif - fcntl(pfd[1], F_SETFD, fcv); - } -#endif + hcl_sys_set_nonblock(pfd[0], nonblock); + hcl_sys_set_nonblock(pfd[1], nonblock); + hcl_sys_set_cloexec(pfd[0], 1); + hcl_sys_set_cloexec(pfd[1], 1); return 0; } @@ -2290,3 +2245,41 @@ void hcl_sys_close_pipes (int pfd[2]) pfd[1] = -1; } } + +int hcl_sys_set_nonblock (int fd, int v) +{ +#if defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK) + int flags; + + if ((flags = fcntl(fd, F_GETFL, 0)) <= -1) return -1; + + if (v) flags |= O_NONBLOCK; + else flags &= ~O_NONBLOCK; + + if (fcntl(fd, F_SETFL, flags) <= -1) return -1; + + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} + +int hcl_sys_set_cloexec (int fd, int v) +{ +#if defined(F_GETFL) && defined(F_SETFL) && defined(FD_CLOEXEC) + int flags; + + if ((flags = fcntl(fd, F_GETFD, 0)) <= -1) return -1; + + if (v) flags |= FD_CLOEXEC; + else flags &= ~FD_CLOEXEC; + + if (fcntl(fd, F_SETFD, flags) <= -1) return -1; + + return 0; +#else + errno = ENOSYS; + return -1; +#endif +}