Last active
November 9, 2023 14:29
-
-
Save pasko/c016b27e9a4d466b641a988861beac41 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// g++ -D_GNU_SOURCE -O2 -Wall async_read_test.cc | |
#include <fcntl.h> | |
#include <poll.h> | |
#include <sys/socket.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <cstdint> | |
#include <iostream> | |
#include <string> | |
#define HANDLE_EINTR(x) \ | |
({ \ | |
decltype(x) eintr_wrapper_result; \ | |
do { \ | |
eintr_wrapper_result = (x); \ | |
} while (eintr_wrapper_result == -1 && \ | |
(errno == EINTR || errno == EAGAIN)); \ | |
eintr_wrapper_result; \ | |
}) | |
int main() { | |
int pipe_fd[2]; | |
if (pipe2(pipe_fd, O_NONBLOCK) == -1) { | |
perror("pipe2"); | |
exit(1); | |
} | |
if (HANDLE_EINTR(write(pipe_fd[1], "H", 1)) != 1) { | |
perror("write"); | |
exit(1); | |
} | |
char read_value; | |
if (HANDLE_EINTR(read(pipe_fd[0], &read_value, 1)) != 1) { | |
perror("read"); | |
exit(1); | |
} | |
if (read_value != 'H') { | |
std::cerr << "Incorrect value read from the pipe" << std::endl; | |
exit(1); | |
} | |
std::cout << "Pipe is working" << std::endl; | |
int read_ret = read(pipe_fd[0], &read_value, 0); | |
std::cout << "Reading zero-length from an empty pipe returns: " | |
<< read_ret | |
<< ", errno=" << errno << std::endl; | |
if (HANDLE_EINTR(write(pipe_fd[1], "N", 1)) != 1) { | |
perror("write2"); | |
exit(1); | |
} | |
read_ret = read(pipe_fd[0], &read_value, 0); | |
std::cout << "Reading from a non-empty pipe returns: " | |
<< read_ret | |
<< ", errno=" << errno << std::endl; | |
struct pollfd poll_fd{}; | |
poll_fd.fd = pipe_fd[0]; | |
poll_fd.events = POLLIN; | |
if (poll(&poll_fd, 1, 0) == -1) { | |
perror("poll"); | |
exit(1); | |
} | |
int revents = poll_fd.revents; | |
if (revents & POLLIN) { | |
std::cout << "Poll non-empty pipe: available data detected" << std::endl; | |
} else if (revents != 0) { | |
std::string err1, err2; | |
err1 = revents == POLLERR ? "POLLERR" : ""; | |
err2 = revents == POLLHUP ? "POLLHUP" : ""; | |
std::cout << "Poll errors: " << err1 << " " << err2 << std::endl; | |
} | |
if (HANDLE_EINTR(read(pipe_fd[0], &read_value, 1)) != 1) { | |
perror("read from non-empty pipe"); | |
exit(1); | |
} | |
if (read_value != 'N') { | |
std::cerr << "Incorrect value read from the pipe" << std::endl; | |
exit(1); | |
} | |
struct pollfd poll_fd2{}; | |
poll_fd2.fd = pipe_fd[0]; | |
poll_fd2.events = POLLIN; | |
if (poll(&poll_fd, 1, 0) == -1) { | |
perror("poll empty pipe"); | |
exit(1); | |
} | |
revents = poll_fd2.revents; | |
if (revents != 0) { | |
std::cerr << "Poll empty pipe: revents=" << revents << std::endl; | |
exit(1); | |
} | |
std::cout << "Poll empty pipe: no data detected" << std::endl; | |
int sockets[2]; | |
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { | |
perror("socketpair"); | |
exit(1); | |
} | |
int bufferSize = 32 * 1024; | |
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); | |
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); | |
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); | |
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); | |
int send_sock = sockets[1]; | |
int recv_sock = sockets[0]; | |
if (sendto(send_sock, "C", 1, MSG_DONTWAIT | MSG_NOSIGNAL, 0, 0) == -1) { | |
perror("sendto"); | |
exit(1); | |
} | |
if (recvfrom(recv_sock, &read_value, 1, MSG_DONTWAIT, NULL, NULL) == -1) { | |
perror("recvfrom"); | |
exit(1); | |
} | |
if (read_value != 'C') { | |
std::cerr << "Incorrect value read from the socket" << std::endl; | |
exit(1); | |
} | |
read_ret = read(recv_sock, &read_value, 0); | |
std::cout << "Reading zero-length from an empty socket returns: " | |
<< read_ret | |
<< ", errno=" << errno << std::endl; | |
if (sendto(send_sock, "D", 1, MSG_DONTWAIT | MSG_NOSIGNAL, 0, 0) == -1) { | |
perror("sendto"); | |
exit(1); | |
} | |
read_ret = read(recv_sock, &read_value, 0); | |
std::cout << "Reading zero-length from a non-empty socket returns: " | |
<< read_ret | |
<< ", errno=" << errno << std::endl; | |
read_ret = read(recv_sock, &read_value, 1); | |
std::cout << "Reading 1 byte from a non-empty socket returns: " | |
<< read_ret | |
<< ", errno=" << errno << std::endl; | |
std::string reading_status_msg; | |
if (read_ret == 1 && read_value == 'D') { | |
std::cout << " Reading was correct" << std::endl; | |
} else if (read_ret != 1) { | |
std::cout << "Wrong number of bytes was read: " << read_ret << std::endl; | |
} else { | |
std::cout << "Wrong value was read: " << read_value << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: