Skip to content

Commit 68fa059

Browse files
committed
fix: fix tests correctness
1 parent d48de38 commit 68fa059

6 files changed

Lines changed: 206 additions & 73 deletions

File tree

ddprof-test-native/src/main/cpp/nativeioblock.c

Lines changed: 104 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,25 @@
2828
struct delayed_write_args {
2929
int fd;
3030
int delay_ms;
31+
int close_after_write;
3132
};
3233

3334
struct delayed_connect_args {
3435
int port;
3536
int delay_ms;
3637
};
3738

39+
enum native_block_kind {
40+
NATIVE_BLOCK_ACCEPT = 3,
41+
NATIVE_BLOCK_POLL = 5,
42+
NATIVE_BLOCK_SELECT = 6,
43+
NATIVE_BLOCK_EPOLL_WAIT = 7
44+
};
45+
46+
static jlong native_blocker(enum native_block_kind kind, int blocker_id) {
47+
return (jlong)(((uint64_t)kind << 32) | (uint32_t)blocker_id);
48+
}
49+
3850
static void sleep_ms(int delay_ms) {
3951
if (delay_ms <= 0) {
4052
return;
@@ -63,13 +75,24 @@ static void throw_out_of_memory(JNIEnv* env) {
6375
}
6476
}
6577

78+
static void throw_timeout(JNIEnv* env, const char* operation) {
79+
jclass exception_class = (*env)->FindClass(env, "java/io/IOException");
80+
if (exception_class != NULL) {
81+
char message[256];
82+
snprintf(message, sizeof(message), "%s timed out", operation);
83+
(*env)->ThrowNew(env, exception_class, message);
84+
}
85+
}
86+
6687
static void* delayed_write(void* arg) {
6788
struct delayed_write_args* args = (struct delayed_write_args*)arg;
6889
sleep_ms(args->delay_ms);
6990
uint64_t value = 1;
7091
while (write(args->fd, &value, sizeof(value)) < 0 && errno == EINTR) {
7192
}
72-
close(args->fd);
93+
if (args->close_after_write) {
94+
close(args->fd);
95+
}
7396
free(args);
7497
return NULL;
7598
}
@@ -91,7 +114,7 @@ static void* delayed_connect(void* arg) {
91114
return NULL;
92115
}
93116

94-
static int start_delayed_write(JNIEnv* env, int fd, int delay_ms) {
117+
static int start_delayed_write(JNIEnv* env, int fd, int delay_ms, int close_after_write) {
95118
struct delayed_write_args* args =
96119
(struct delayed_write_args*)malloc(sizeof(struct delayed_write_args));
97120
if (args == NULL) {
@@ -100,6 +123,7 @@ static int start_delayed_write(JNIEnv* env, int fd, int delay_ms) {
100123
}
101124
args->fd = fd;
102125
args->delay_ms = delay_ms;
126+
args->close_after_write = close_after_write;
103127
pthread_t thread;
104128
int rc = pthread_create(&thread, NULL, delayed_write, args);
105129
if (rc != 0) {
@@ -133,77 +157,94 @@ static int start_delayed_connect(JNIEnv* env, int port, int delay_ms) {
133157
return 0;
134158
}
135159

136-
static void block_with_poll_like(JNIEnv* env, jint delay_ms, int use_ppoll) {
160+
static jlong block_with_poll_like(JNIEnv* env, jint delay_ms, int use_ppoll) {
137161
int fds[2];
138162
if (pipe(fds) != 0) {
139163
throw_io_exception(env, "pipe");
140-
return;
164+
return 0;
141165
}
142-
if (start_delayed_write(env, fds[1], delay_ms) != 0) {
166+
if (start_delayed_write(env, fds[1], delay_ms, 1) != 0) {
143167
close(fds[0]);
144168
close(fds[1]);
145-
return;
169+
return 0;
146170
}
147171

148172
struct pollfd pfd;
149173
pfd.fd = fds[0];
150174
pfd.events = POLLIN;
151175
pfd.revents = 0;
152176
int rc;
153-
if (use_ppoll) {
154-
rc = ppoll(&pfd, 1, NULL, NULL);
155-
} else {
156-
rc = poll(&pfd, 1, -1);
157-
}
177+
do {
178+
if (use_ppoll) {
179+
struct timespec timeout_ts = {5, 0};
180+
rc = ppoll(&pfd, 1, &timeout_ts, NULL);
181+
} else {
182+
rc = poll(&pfd, 1, 5000);
183+
}
184+
} while (rc < 0 && errno == EINTR);
158185
close(fds[0]);
159186
if (rc < 0) {
160187
throw_io_exception(env, use_ppoll ? "ppoll" : "poll");
188+
return 0;
189+
} else if (rc == 0) {
190+
throw_timeout(env, use_ppoll ? "ppoll" : "poll");
191+
return 0;
161192
}
193+
return native_blocker(NATIVE_BLOCK_POLL, 0);
162194
}
163195

164-
JNIEXPORT void JNICALL
196+
JNIEXPORT jlong JNICALL
165197
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingPpoll(
166198
JNIEnv* env, jclass clazz, jint delay_ms) {
167199
(void)clazz;
168-
block_with_poll_like(env, delay_ms, 1);
200+
return block_with_poll_like(env, delay_ms, 1);
169201
}
170202

171-
JNIEXPORT void JNICALL
203+
JNIEXPORT jlong JNICALL
172204
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingPselect(
173205
JNIEnv* env, jclass clazz, jint delay_ms) {
174206
(void)clazz;
175207
int fds[2];
176208
if (pipe(fds) != 0) {
177209
throw_io_exception(env, "pipe");
178-
return;
210+
return 0;
179211
}
180-
if (start_delayed_write(env, fds[1], delay_ms) != 0) {
212+
if (start_delayed_write(env, fds[1], delay_ms, 1) != 0) {
181213
close(fds[0]);
182214
close(fds[1]);
183-
return;
215+
return 0;
184216
}
185217

186-
fd_set readfds;
187-
FD_ZERO(&readfds);
188-
FD_SET(fds[0], &readfds);
189-
int rc = pselect(fds[0] + 1, &readfds, NULL, NULL, NULL, NULL);
218+
int rc;
219+
do {
220+
fd_set readfds;
221+
FD_ZERO(&readfds);
222+
FD_SET(fds[0], &readfds);
223+
struct timespec timeout = {5, 0};
224+
rc = pselect(fds[0] + 1, &readfds, NULL, NULL, &timeout, NULL);
225+
} while (rc < 0 && errno == EINTR);
190226
close(fds[0]);
191227
if (rc < 0) {
192228
throw_io_exception(env, "pselect");
229+
return 0;
230+
} else if (rc == 0) {
231+
throw_timeout(env, "pselect");
232+
return 0;
193233
}
234+
return native_blocker(NATIVE_BLOCK_SELECT, 0);
194235
}
195236

196-
static void block_with_epoll(JNIEnv* env, jint delay_ms, int use_pwait) {
237+
static jlong block_with_epoll(JNIEnv* env, jint delay_ms, int use_pwait) {
197238
int event_fd = eventfd(0, EFD_CLOEXEC);
198239
if (event_fd < 0) {
199240
throw_io_exception(env, "eventfd");
200-
return;
241+
return 0;
201242
}
202243
int epfd = epoll_create1(EPOLL_CLOEXEC);
203244
if (epfd < 0) {
204245
close(event_fd);
205246
throw_io_exception(env, "epoll_create1");
206-
return;
247+
return 0;
207248
}
208249
struct epoll_event event;
209250
memset(&event, 0, sizeof(event));
@@ -213,49 +254,58 @@ static void block_with_epoll(JNIEnv* env, jint delay_ms, int use_pwait) {
213254
close(epfd);
214255
close(event_fd);
215256
throw_io_exception(env, "epoll_ctl");
216-
return;
257+
return 0;
217258
}
218-
if (start_delayed_write(env, event_fd, delay_ms) != 0) {
259+
if (start_delayed_write(env, event_fd, delay_ms, 0) != 0) {
219260
close(epfd);
220261
close(event_fd);
221-
return;
262+
return 0;
222263
}
223264

224265
struct epoll_event out_event;
225266
int rc;
226-
if (use_pwait) {
227-
rc = epoll_pwait(epfd, &out_event, 1, -1, NULL);
228-
} else {
229-
rc = epoll_wait(epfd, &out_event, 1, -1);
230-
}
267+
do {
268+
if (use_pwait) {
269+
rc = epoll_pwait(epfd, &out_event, 1, 5000, NULL);
270+
} else {
271+
rc = epoll_wait(epfd, &out_event, 1, 5000);
272+
}
273+
} while (rc < 0 && errno == EINTR);
274+
jlong blocker = native_blocker(NATIVE_BLOCK_EPOLL_WAIT, epfd);
231275
close(epfd);
276+
close(event_fd);
232277
if (rc < 0) {
233278
throw_io_exception(env, use_pwait ? "epoll_pwait" : "epoll_wait");
279+
return 0;
280+
} else if (rc == 0) {
281+
throw_timeout(env, use_pwait ? "epoll_pwait" : "epoll_wait");
282+
return 0;
234283
}
284+
return blocker;
235285
}
236286

237-
JNIEXPORT void JNICALL
287+
JNIEXPORT jlong JNICALL
238288
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingEpollWait(
239289
JNIEnv* env, jclass clazz, jint delay_ms) {
240290
(void)clazz;
241-
block_with_epoll(env, delay_ms, 0);
291+
return block_with_epoll(env, delay_ms, 0);
242292
}
243293

244-
JNIEXPORT void JNICALL
294+
JNIEXPORT jlong JNICALL
245295
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingEpollPwait(
246296
JNIEnv* env, jclass clazz, jint delay_ms) {
247297
(void)clazz;
248-
block_with_epoll(env, delay_ms, 1);
298+
return block_with_epoll(env, delay_ms, 1);
249299
}
250300

251-
JNIEXPORT void JNICALL
301+
JNIEXPORT jlong JNICALL
252302
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingAccept4(
253303
JNIEnv* env, jclass clazz, jint delay_ms) {
254304
(void)clazz;
255305
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
256306
if (server_fd < 0) {
257307
throw_io_exception(env, "socket");
258-
return;
308+
return 0;
259309
}
260310
int one = 1;
261311
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
@@ -269,28 +319,31 @@ Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingAccept4(
269319
listen(server_fd, 1) != 0) {
270320
close(server_fd);
271321
throw_io_exception(env, "bind/listen");
272-
return;
322+
return 0;
273323
}
274324

275325
socklen_t addr_len = sizeof(addr);
276326
if (getsockname(server_fd, (struct sockaddr*)&addr, &addr_len) != 0) {
277327
close(server_fd);
278328
throw_io_exception(env, "getsockname");
279-
return;
329+
return 0;
280330
}
281331
if (start_delayed_connect(env, ntohs(addr.sin_port), delay_ms) != 0) {
282332
close(server_fd);
283-
return;
333+
return 0;
284334
}
285335

336+
jlong blocker = native_blocker(NATIVE_BLOCK_ACCEPT, server_fd);
286337
int accepted_fd = accept4(server_fd, NULL, NULL, SOCK_CLOEXEC);
287338
if (accepted_fd >= 0) {
288339
close(accepted_fd);
289340
}
290341
close(server_fd);
291342
if (accepted_fd < 0) {
292343
throw_io_exception(env, "accept4");
344+
return 0;
293345
}
346+
return blocker;
294347
}
295348

296349
#else
@@ -302,44 +355,49 @@ static void unsupported(JNIEnv* env) {
302355
}
303356
}
304357

305-
JNIEXPORT void JNICALL
358+
JNIEXPORT jlong JNICALL
306359
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingAccept4(
307360
JNIEnv* env, jclass clazz, jint delay_ms) {
308361
(void)clazz;
309362
(void)delay_ms;
310363
unsupported(env);
364+
return 0;
311365
}
312366

313-
JNIEXPORT void JNICALL
367+
JNIEXPORT jlong JNICALL
314368
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingPpoll(
315369
JNIEnv* env, jclass clazz, jint delay_ms) {
316370
(void)clazz;
317371
(void)delay_ms;
318372
unsupported(env);
373+
return 0;
319374
}
320375

321-
JNIEXPORT void JNICALL
376+
JNIEXPORT jlong JNICALL
322377
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingPselect(
323378
JNIEnv* env, jclass clazz, jint delay_ms) {
324379
(void)clazz;
325380
(void)delay_ms;
326381
unsupported(env);
382+
return 0;
327383
}
328384

329-
JNIEXPORT void JNICALL
385+
JNIEXPORT jlong JNICALL
330386
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingEpollWait(
331387
JNIEnv* env, jclass clazz, jint delay_ms) {
332388
(void)clazz;
333389
(void)delay_ms;
334390
unsupported(env);
391+
return 0;
335392
}
336393

337-
JNIEXPORT void JNICALL
394+
JNIEXPORT jlong JNICALL
338395
Java_com_datadoghq_profiler_wallclock_NativeIoBlockHelper_blockingEpollPwait(
339396
JNIEnv* env, jclass clazz, jint delay_ms) {
340397
(void)clazz;
341398
(void)delay_ms;
342399
unsupported(env);
400+
return 0;
343401
}
344402

345403
#endif

0 commit comments

Comments
 (0)