Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: MIT */ |
| 2 | /* |
| 3 | * Check that writev on a socket that has been shutdown(2) fails |
| 4 | * |
| 5 | */ |
| 6 | #include <stdio.h> |
| 7 | #include <stdlib.h> |
| 8 | #include <stdint.h> |
| 9 | #include <assert.h> |
| 10 | |
| 11 | #include <errno.h> |
| 12 | #include <fcntl.h> |
| 13 | #include <unistd.h> |
| 14 | #include <sys/socket.h> |
| 15 | #include <sys/un.h> |
| 16 | #include <netinet/tcp.h> |
| 17 | #include <netinet/in.h> |
| 18 | |
| 19 | #include "liburing.h" |
| 20 | |
Jens Axboe | 7e1447c | 2020-09-05 17:06:43 -0600 | [diff] [blame] | 21 | static void sig_pipe(int sig) |
| 22 | { |
| 23 | } |
| 24 | |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 25 | int main(int argc, char *argv[]) |
| 26 | { |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 27 | int p_fd[2], ret; |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 28 | int32_t recv_s0; |
| 29 | int32_t val = 1; |
| 30 | struct sockaddr_in addr; |
| 31 | |
| 32 | if (argc > 1) |
| 33 | return 0; |
| 34 | |
Jens Axboe | d0984a9 | 2021-02-17 14:26:57 -0700 | [diff] [blame^] | 35 | srand(getpid()); |
| 36 | |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 37 | recv_s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); |
| 38 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 39 | ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); |
| 40 | assert(ret != -1); |
| 41 | ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); |
| 42 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 43 | |
| 44 | addr.sin_family = AF_INET; |
Jens Axboe | d0984a9 | 2021-02-17 14:26:57 -0700 | [diff] [blame^] | 45 | addr.sin_port = (rand() % 61440) + 4096; |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 46 | addr.sin_addr.s_addr = 0x0100007fU; |
| 47 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 48 | ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); |
| 49 | assert(ret != -1); |
| 50 | ret = listen(recv_s0, 128); |
| 51 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 52 | |
| 53 | p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); |
| 54 | |
| 55 | val = 1; |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 56 | ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); |
| 57 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 58 | |
| 59 | int32_t flags = fcntl(p_fd[1], F_GETFL, 0); |
| 60 | assert(flags != -1); |
| 61 | |
| 62 | flags |= O_NONBLOCK; |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 63 | ret = fcntl(p_fd[1], F_SETFL, flags); |
| 64 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 65 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 66 | ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr)); |
| 67 | assert(ret == -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 68 | |
| 69 | flags = fcntl(p_fd[1], F_GETFL, 0); |
| 70 | assert(flags != -1); |
| 71 | |
| 72 | flags &= ~O_NONBLOCK; |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 73 | ret = fcntl(p_fd[1], F_SETFL, flags); |
| 74 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 75 | |
| 76 | p_fd[0] = accept(recv_s0, NULL, NULL); |
| 77 | assert(p_fd[0] != -1); |
| 78 | |
Jens Axboe | 7e1447c | 2020-09-05 17:06:43 -0600 | [diff] [blame] | 79 | signal(SIGPIPE, sig_pipe); |
| 80 | |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 81 | while (1) { |
| 82 | int32_t code; |
| 83 | socklen_t code_len = sizeof(code); |
| 84 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 85 | ret = getsockopt(p_fd[1], SOL_SOCKET, SO_ERROR, &code, &code_len); |
| 86 | assert(ret != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 87 | |
| 88 | if (!code) |
| 89 | break; |
| 90 | } |
| 91 | |
| 92 | struct io_uring m_io_uring; |
| 93 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 94 | ret = io_uring_queue_init(32, &m_io_uring, 0); |
| 95 | assert(ret >= 0); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 96 | |
| 97 | { |
| 98 | struct io_uring_cqe *cqe; |
| 99 | struct io_uring_sqe *sqe; |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 100 | int res; |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 101 | |
| 102 | sqe = io_uring_get_sqe(&m_io_uring); |
| 103 | io_uring_prep_shutdown(sqe, p_fd[1], SHUT_WR); |
| 104 | sqe->user_data = 1; |
| 105 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 106 | res = io_uring_submit_and_wait(&m_io_uring, 1); |
| 107 | assert(res != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 108 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 109 | res = io_uring_wait_cqe(&m_io_uring, &cqe); |
| 110 | if (res < 0) { |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 111 | fprintf(stderr, "wait: %s\n", strerror(-ret)); |
| 112 | goto err; |
| 113 | } |
| 114 | |
| 115 | if (cqe->res) { |
| 116 | if (cqe->res == -EINVAL) { |
| 117 | fprintf(stdout, "Shutdown not supported, skipping\n"); |
| 118 | goto done; |
| 119 | } |
| 120 | fprintf(stderr, "writev: %d\n", cqe->res); |
| 121 | goto err; |
| 122 | } |
| 123 | |
| 124 | io_uring_cqe_seen(&m_io_uring, cqe); |
| 125 | } |
| 126 | |
| 127 | { |
| 128 | struct io_uring_cqe *cqe; |
| 129 | struct io_uring_sqe *sqe; |
| 130 | struct iovec iov[1]; |
| 131 | char send_buff[128]; |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 132 | int res; |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 133 | |
| 134 | iov[0].iov_base = send_buff; |
| 135 | iov[0].iov_len = sizeof(send_buff); |
| 136 | |
| 137 | sqe = io_uring_get_sqe(&m_io_uring); |
| 138 | assert(sqe != NULL); |
| 139 | |
| 140 | io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0); |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 141 | res = io_uring_submit_and_wait(&m_io_uring, 1); |
| 142 | assert(res != -1); |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 143 | |
Ryan Sharpelletti | e3adbfc | 2020-10-27 21:04:11 +0000 | [diff] [blame] | 144 | res = io_uring_wait_cqe(&m_io_uring, &cqe); |
| 145 | if (res < 0) { |
Jens Axboe | 8a3a8d7 | 2020-09-05 15:53:51 -0600 | [diff] [blame] | 146 | fprintf(stderr, "wait: %s\n", strerror(-ret)); |
| 147 | goto err; |
| 148 | } |
| 149 | |
| 150 | if (cqe->res != -EPIPE) { |
| 151 | fprintf(stderr, "writev: %d\n", cqe->res); |
| 152 | goto err; |
| 153 | } |
| 154 | io_uring_cqe_seen(&m_io_uring, cqe); |
| 155 | } |
| 156 | |
| 157 | done: |
| 158 | io_uring_queue_exit(&m_io_uring); |
| 159 | return 0; |
| 160 | err: |
| 161 | io_uring_queue_exit(&m_io_uring); |
| 162 | return 1; |
| 163 | } |