Even more flexible management of poll data
This commit is contained in:
@@ -47,6 +47,12 @@
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
#define IO_BUZ_SZ 8192
|
#define IO_BUZ_SZ 8192
|
||||||
|
#define remove_i_from_array(array, i, count) { \
|
||||||
|
(count)--; \
|
||||||
|
if ((i) < (count)) { \
|
||||||
|
memmove((array) + (i), (array) + (i) + 1, sizeof((array)[0]) * ((count) - (i))); \
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
typedef struct transfer_buf {
|
typedef struct transfer_buf {
|
||||||
char *buf;
|
char *buf;
|
||||||
@@ -454,24 +460,31 @@ read_signals(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pollees {
|
||||||
|
struct pollfd poll_data[8];
|
||||||
|
struct {
|
||||||
|
int self_ttyfd, signal_read_fd, socket_fd, child_master_fd;
|
||||||
|
} idx;
|
||||||
|
size_t num_fds;
|
||||||
|
};
|
||||||
|
static struct pollees pollees = {0};
|
||||||
|
|
||||||
|
#define register_for_poll(which) pollees.poll_data[pollees.num_fds].fd = which; pollees.poll_data[pollees.num_fds].events = POLLIN; pollees.idx.which = pollees.num_fds++;
|
||||||
|
#define unregister_for_poll(which) if (pollees.idx.which > -1) { remove_i_from_array(pollees.poll_data, pollees.idx.which, pollees.num_fds); pollees.idx.which = -1; }
|
||||||
|
#define set_poll_events(which, val) if (pollees.idx.which > -1) { pollees.poll_data[pollees.idx.which].events = (val); }
|
||||||
|
#define poll_revents(which) ((pollees.idx.which > -1) ? pollees.poll_data[pollees.idx.which].revents : 0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
loop(void) {
|
loop(void) {
|
||||||
#define fail(s) { print_error(s, errno); return; }
|
#define fail(s) { print_error(s, errno); return; }
|
||||||
#define pd(which) poll_data[which##_idx]
|
#define check_fd(name) { if (poll_revents(name) & POLLERR) { pe("File descriptor %s failed", #name); return; } if (poll_revents(name) & POLLHUP) { pe("File descriptor %s hungup", #name); return; } }
|
||||||
#define check_fd(name) { if (pd(name).revents & POLLERR) { pe("File descriptor %s failed", #name); return; } if (pd(name).revents & POLLHUP) { pe("File descriptor %s hungup", #name); return; } }
|
register_for_poll(self_ttyfd); register_for_poll(socket_fd); register_for_poll(signal_read_fd); register_for_poll(child_master_fd);
|
||||||
struct pollfd poll_data[4];
|
|
||||||
enum { self_ttyfd_idx, signal_read_fd_idx, socket_fd_idx, child_master_fd_idx };
|
|
||||||
#define init(name) pd(name).fd = name; pd(name).events = POLLIN;
|
|
||||||
init(self_ttyfd); init(socket_fd); init(signal_read_fd); init(child_master_fd);
|
|
||||||
#undef init
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int ret;
|
int ret;
|
||||||
pd(self_ttyfd).events = (to_child_tty.sz < IO_BUZ_SZ ? POLLIN : 0) | (from_child_tty.sz ? POLLOUT : 0);
|
set_poll_events(self_ttyfd, (to_child_tty.sz < IO_BUZ_SZ ? POLLIN : 0) | (from_child_tty.sz ? POLLOUT : 0));
|
||||||
if (socket_fd > -1) pd(socket_fd).events = POLLIN | (launch_msg.iov_len ? POLLOUT : 0);
|
set_poll_events(socket_fd, POLLIN | (launch_msg.iov_len ? POLLOUT : 0));
|
||||||
else pd(socket_fd).events = 0;
|
set_poll_events(child_master_fd, (from_child_tty.sz < IO_BUZ_SZ ? POLLIN : 0) | (to_child_tty.sz ? POLLOUT : 0));
|
||||||
if (child_master_fd > -1) pd(child_master_fd).events = (from_child_tty.sz < IO_BUZ_SZ ? POLLIN : 0) | (to_child_tty.sz ? POLLOUT : 0);
|
|
||||||
else pd(child_master_fd).events = 0;
|
|
||||||
|
|
||||||
if (window_size_dirty && child_master_fd > -1 ) {
|
if (window_size_dirty && child_master_fd > -1 ) {
|
||||||
if (!get_window_size()) fail("getting window size for self tty failed");
|
if (!get_window_size()) fail("getting window size for self tty failed");
|
||||||
@@ -479,44 +492,43 @@ loop(void) {
|
|||||||
window_size_dirty = false;
|
window_size_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysz(poll_data); i++) poll_data[i].revents = 0;
|
for (size_t i = 0; i < pollees.num_fds; i++) pollees.poll_data[i].revents = 0;
|
||||||
while ((ret = poll(poll_data, arraysz(poll_data), -1)) == -1) { if (errno != EINTR) fail("poll() failed"); }
|
while ((ret = poll(pollees.poll_data, pollees.num_fds, -1)) == -1) { if (errno != EINTR) fail("poll() failed"); }
|
||||||
if (!ret) continue;
|
if (!ret) continue;
|
||||||
|
|
||||||
if (pd(child_master_fd).revents & POLLIN) if (!read_or_transfer_from_child_tty()) fail("reading from child tty failed");
|
if (poll_revents(child_master_fd) & POLLIN) if (!read_or_transfer_from_child_tty()) fail("reading from child tty failed");
|
||||||
if (pd(self_ttyfd).revents & POLLOUT) if (!from_child_to_self()) fail("writing to self tty failed");
|
if (poll_revents(self_ttyfd) & POLLOUT) if (!from_child_to_self()) fail("writing to self tty failed");
|
||||||
if (pd(self_ttyfd).revents & POLLIN) if (!read_or_transfer_from_self_tty()) fail("reading from self tty failed");
|
if (poll_revents(self_ttyfd) & POLLIN) if (!read_or_transfer_from_self_tty()) fail("reading from self tty failed");
|
||||||
if (pd(child_master_fd).revents & POLLOUT) if (!from_self_to_child()) fail("writing to child tty failed");
|
if (poll_revents(child_master_fd) & POLLOUT) if (!from_self_to_child()) fail("writing to child tty failed");
|
||||||
if (pd(child_master_fd).revents & POLLHUP) {
|
if (poll_revents(child_master_fd) & POLLHUP) {
|
||||||
// child has closed its tty, wait for exit code from prewarm zygote
|
// child has closed its tty, wait for exit code from prewarm zygote
|
||||||
safe_close(child_master_fd); child_master_fd = -1;
|
safe_close(child_master_fd); child_master_fd = -1;
|
||||||
|
unregister_for_poll(child_master_fd);
|
||||||
if (!child_pid) return;
|
if (!child_pid) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_fd(self_ttyfd);
|
check_fd(self_ttyfd); check_fd(child_master_fd); check_fd(signal_read_fd);
|
||||||
if (child_master_fd > -1) check_fd(child_master_fd);
|
|
||||||
check_fd(signal_read_fd);
|
|
||||||
|
|
||||||
// signal_read_fd
|
// signal_read_fd
|
||||||
if (pd(signal_read_fd).revents & POLLIN) if (!read_signals()) fail("reading from signal fd failed");
|
if (poll_revents(signal_read_fd) & POLLIN) if (!read_signals()) fail("reading from signal fd failed");
|
||||||
|
|
||||||
// socket_fd
|
// socket_fd
|
||||||
if (pd(socket_fd).revents & POLLERR) {
|
if (poll_revents(socket_fd) & POLLERR) {
|
||||||
print_error("File descriptor socket_fd failed", 0); return;
|
print_error("File descriptor socket_fd failed", 0); return;
|
||||||
}
|
}
|
||||||
if (pd(socket_fd).revents & POLLIN) {
|
if (poll_revents(socket_fd) & POLLIN) {
|
||||||
if (!read_child_data()) fail("reading information about child failed");
|
if (!read_child_data()) fail("reading information about child failed");
|
||||||
}
|
}
|
||||||
if (pd(socket_fd).revents & POLLHUP) {
|
if (poll_revents(socket_fd) & POLLHUP) {
|
||||||
if (from_child_buf[0]) { parse_int(from_child_buf, &exit_status); }
|
if (from_child_buf[0]) { parse_int(from_child_buf, &exit_status); }
|
||||||
child_pid = 0;
|
child_pid = 0; safe_close(socket_fd); socket_fd = -1;
|
||||||
|
unregister_for_poll(socket_fd);
|
||||||
if (child_master_fd < 0) return;
|
if (child_master_fd < 0) return;
|
||||||
}
|
}
|
||||||
if (pd(socket_fd).revents & POLLOUT) {
|
if (poll_revents(socket_fd) & POLLOUT) {
|
||||||
if (!send_launch_msg()) fail("sending launch message failed");
|
if (!send_launch_msg()) fail("sending launch message failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef pd
|
|
||||||
#undef check_fd
|
#undef check_fd
|
||||||
#undef fail
|
#undef fail
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user