blob: 5aa13711b34894342e3319137d13c3f88f009c9b [file] [log] [blame]
Jens Axboe8a3a8d72020-09-05 15:53:51 -06001/* 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 Axboe7e1447c2020-09-05 17:06:43 -060021static void sig_pipe(int sig)
22{
23}
24
Jens Axboe8a3a8d72020-09-05 15:53:51 -060025int main(int argc, char *argv[])
26{
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000027 int p_fd[2], ret;
Jens Axboe8a3a8d72020-09-05 15:53:51 -060028 int32_t recv_s0;
29 int32_t val = 1;
30 struct sockaddr_in addr;
31
32 if (argc > 1)
33 return 0;
34
Jens Axboed0984a92021-02-17 14:26:57 -070035 srand(getpid());
36
Jens Axboe8a3a8d72020-09-05 15:53:51 -060037 recv_s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
38
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000039 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 Axboe8a3a8d72020-09-05 15:53:51 -060043
44 addr.sin_family = AF_INET;
Jens Axboed0984a92021-02-17 14:26:57 -070045 addr.sin_port = (rand() % 61440) + 4096;
Jens Axboe8a3a8d72020-09-05 15:53:51 -060046 addr.sin_addr.s_addr = 0x0100007fU;
47
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000048 ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr));
49 assert(ret != -1);
50 ret = listen(recv_s0, 128);
51 assert(ret != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060052
53 p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
54
55 val = 1;
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000056 ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
57 assert(ret != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060058
59 int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
60 assert(flags != -1);
61
62 flags |= O_NONBLOCK;
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000063 ret = fcntl(p_fd[1], F_SETFL, flags);
64 assert(ret != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060065
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000066 ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
67 assert(ret == -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060068
69 flags = fcntl(p_fd[1], F_GETFL, 0);
70 assert(flags != -1);
71
72 flags &= ~O_NONBLOCK;
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000073 ret = fcntl(p_fd[1], F_SETFL, flags);
74 assert(ret != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060075
76 p_fd[0] = accept(recv_s0, NULL, NULL);
77 assert(p_fd[0] != -1);
78
Jens Axboe7e1447c2020-09-05 17:06:43 -060079 signal(SIGPIPE, sig_pipe);
80
Jens Axboe8a3a8d72020-09-05 15:53:51 -060081 while (1) {
82 int32_t code;
83 socklen_t code_len = sizeof(code);
84
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000085 ret = getsockopt(p_fd[1], SOL_SOCKET, SO_ERROR, &code, &code_len);
86 assert(ret != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060087
88 if (!code)
89 break;
90 }
91
92 struct io_uring m_io_uring;
93
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +000094 ret = io_uring_queue_init(32, &m_io_uring, 0);
95 assert(ret >= 0);
Jens Axboe8a3a8d72020-09-05 15:53:51 -060096
97 {
98 struct io_uring_cqe *cqe;
99 struct io_uring_sqe *sqe;
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +0000100 int res;
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600101
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 Sharpellettie3adbfc2020-10-27 21:04:11 +0000106 res = io_uring_submit_and_wait(&m_io_uring, 1);
107 assert(res != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600108
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +0000109 res = io_uring_wait_cqe(&m_io_uring, &cqe);
110 if (res < 0) {
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600111 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 Sharpellettie3adbfc2020-10-27 21:04:11 +0000132 int res;
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600133
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 Sharpellettie3adbfc2020-10-27 21:04:11 +0000141 res = io_uring_submit_and_wait(&m_io_uring, 1);
142 assert(res != -1);
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600143
Ryan Sharpellettie3adbfc2020-10-27 21:04:11 +0000144 res = io_uring_wait_cqe(&m_io_uring, &cqe);
145 if (res < 0) {
Jens Axboe8a3a8d72020-09-05 15:53:51 -0600146 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
157done:
158 io_uring_queue_exit(&m_io_uring);
159 return 0;
160err:
161 io_uring_queue_exit(&m_io_uring);
162 return 1;
163}