Variant f_socket_select(VRefParam read, VRefParam write, VRefParam except, CVarRef vtv_sec, int tv_usec /* = 0 */) { int count = 0; if (!read.isNull()) { count += read.toArray().size(); } if (!write.isNull()) { count += write.toArray().size(); } if (!except.isNull()) { count += except.toArray().size(); } if (!count) { return false; } struct pollfd *fds = (struct pollfd *)calloc(count, sizeof(struct pollfd)); count = 0; if (!read.isNull()) { sock_array_to_fd_set(read.toArray(), fds, count, POLLIN); } if (!write.isNull()) { sock_array_to_fd_set(write.toArray(), fds, count, POLLOUT); } if (!except.isNull()) { sock_array_to_fd_set(except.toArray(), fds, count, POLLPRI); } IOStatusHelper io("socket_select"); int timeout_ms = -1; if (!vtv_sec.isNull()) { timeout_ms = vtv_sec.toInt32() * 1000 + tv_usec / 1000; } int retval = poll(fds, count, timeout_ms); if (retval == -1) { raise_warning("unable to select [%d]: %s", errno, Util::safe_strerror(errno).c_str()); free(fds); return false; } count = 0; int nfds = 0; if (!read.isNull()) { sock_array_from_fd_set(read, fds, nfds, count, POLLIN|POLLERR); } if (!write.isNull()) { sock_array_from_fd_set(write, fds, nfds, count, POLLOUT|POLLERR); } if (!except.isNull()) { sock_array_from_fd_set(except, fds, nfds, count, POLLPRI|POLLERR); } free(fds); return count; }
Variant HHVM_FUNCTION(socket_select, VRefParam read, VRefParam write, VRefParam except, const Variant& vtv_sec, int tv_usec /* = 0 */) { int count = 0; if (!read.isNull()) { count += read.toArray().size(); } if (!write.isNull()) { count += write.toArray().size(); } if (!except.isNull()) { count += except.toArray().size(); } if (!count) { return false; } struct pollfd *fds = (struct pollfd *)calloc(count, sizeof(struct pollfd)); count = 0; if (!read.isNull()) { sock_array_to_fd_set(read.toArray(), fds, count, POLLIN); } if (!write.isNull()) { sock_array_to_fd_set(write.toArray(), fds, count, POLLOUT); } if (!except.isNull()) { sock_array_to_fd_set(except.toArray(), fds, count, POLLPRI); } if (!count) { raise_warning("no resource arrays were passed to select"); free(fds); return false; } IOStatusHelper io("socket_select"); int timeout_ms = -1; if (!vtv_sec.isNull()) { timeout_ms = vtv_sec.toInt32() * 1000 + tv_usec / 1000; } /* slight hack to support buffered data; if there is data sitting in the * read buffer of any of the streams in the read array, let's pretend * that we selected, but return only the readable sockets */ if (!read.isNull()) { auto hasData = Array::Create(); for (ArrayIter iter(read.toArray()); iter; ++iter) { auto file = cast<File>(iter.second()); if (file->bufferedLen() > 0) { hasData.append(iter.second()); } } if (hasData.size() > 0) { if (!write.isNull()) { write = empty_array(); } if (!except.isNull()) { except = empty_array(); } read = hasData; free(fds); return hasData.size(); } } int retval = poll(fds, count, timeout_ms); if (retval == -1) { raise_warning("unable to select [%d]: %s", errno, folly::errnoStr(errno).c_str()); free(fds); return false; } count = 0; int nfds = 0; if (!read.isNull()) { sock_array_from_fd_set(read, fds, nfds, count, POLLIN|POLLERR|POLLHUP); } if (!write.isNull()) { sock_array_from_fd_set(write, fds, nfds, count, POLLOUT|POLLERR); } if (!except.isNull()) { sock_array_from_fd_set(except, fds, nfds, count, POLLPRI|POLLERR); } free(fds); return count; }