Skip to content

Commit 1ce12c4

Browse files
Long YangPaul Hohensee
authored andcommitted
8312065: Socket.connect does not timeout when profiling
Reviewed-by: phh, vtewari, apangin
1 parent fee0229 commit 1ce12c4

File tree

4 files changed

+162
-74
lines changed

4 files changed

+162
-74
lines changed

src/java.base/aix/native/libnet/aix_close.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -388,50 +388,50 @@ int NET_SocketClose(int fd) {
388388
/************** Basic I/O operations here ***************/
389389

390390
/*
391-
* Macro to perform a blocking IO operation. Restarts
392-
* automatically if interrupted by signal (other than
393-
* our wakeup signal)
391+
* Macro to perform a blocking IO operation.
392+
* If interrupted by signal (other than our wakeup signal), and if RETRY is true,
393+
* then restarts automatically
394394
*/
395-
#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
396-
int ret; \
397-
threadEntry_t self; \
398-
fdEntry_t *fdEntry = getFdEntry(FD); \
399-
if (fdEntry == NULL) { \
400-
errno = EBADF; \
401-
return -1; \
402-
} \
403-
do { \
404-
startOp(fdEntry, &self); \
405-
ret = FUNC; \
406-
endOp(fdEntry, &self); \
407-
} while (ret == -1 && errno == EINTR); \
408-
return ret; \
395+
#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
396+
int ret; \
397+
threadEntry_t self; \
398+
fdEntry_t *fdEntry = getFdEntry(FD); \
399+
if (fdEntry == NULL) { \
400+
errno = EBADF; \
401+
return -1; \
402+
} \
403+
do { \
404+
startOp(fdEntry, &self); \
405+
ret = FUNC; \
406+
endOp(fdEntry, &self); \
407+
} while ((RETRY) && ret == -1 && errno == EINTR); \
408+
return ret; \
409409
}
410410

411411
int NET_Read(int s, void* buf, size_t len) {
412-
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
412+
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
413413
}
414414

415415
int NET_NonBlockingRead(int s, void* buf, size_t len) {
416-
BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK));
416+
BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK), JNI_TRUE );
417417
}
418418

419419
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
420420
struct sockaddr *from, socklen_t *fromlen) {
421-
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
421+
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
422422
}
423423

424424
int NET_Send(int s, void *msg, int len, unsigned int flags) {
425-
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
425+
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
426426
}
427427

428428
int NET_SendTo(int s, const void *msg, int len, unsigned int
429429
flags, const struct sockaddr *to, int tolen) {
430-
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
430+
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
431431
}
432432

433433
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
434-
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
434+
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
435435
}
436436

437437
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
@@ -489,7 +489,7 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
489489
}
490490

491491
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
492-
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
492+
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
493493
}
494494

495495
/*

src/java.base/linux/native/libnet/linux_close.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -345,58 +345,58 @@ int NET_SocketClose(int fd) {
345345
/************** Basic I/O operations here ***************/
346346

347347
/*
348-
* Macro to perform a blocking IO operation. Restarts
349-
* automatically if interrupted by signal (other than
350-
* our wakeup signal)
348+
* Macro to perform a blocking IO operation.
349+
* If interrupted by signal (other than our wakeup signal), and if RETRY is true,
350+
* then restarts automatically
351351
*/
352-
#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
353-
int ret; \
354-
threadEntry_t self; \
355-
fdEntry_t *fdEntry = getFdEntry(FD); \
356-
if (fdEntry == NULL) { \
357-
errno = EBADF; \
358-
return -1; \
359-
} \
360-
do { \
361-
startOp(fdEntry, &self); \
362-
ret = FUNC; \
363-
endOp(fdEntry, &self); \
364-
} while (ret == -1 && errno == EINTR); \
365-
return ret; \
352+
#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
353+
int ret; \
354+
threadEntry_t self; \
355+
fdEntry_t *fdEntry = getFdEntry(FD); \
356+
if (fdEntry == NULL) { \
357+
errno = EBADF; \
358+
return -1; \
359+
} \
360+
do { \
361+
startOp(fdEntry, &self); \
362+
ret = FUNC; \
363+
endOp(fdEntry, &self); \
364+
} while ((RETRY) && ret == -1 && errno == EINTR); \
365+
return ret; \
366366
}
367367

368368
int NET_Read(int s, void* buf, size_t len) {
369-
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
369+
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
370370
}
371371

372372
int NET_NonBlockingRead(int s, void* buf, size_t len) {
373-
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT) );
373+
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE );
374374
}
375375

376376
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
377377
struct sockaddr *from, socklen_t *fromlen) {
378-
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
378+
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
379379
}
380380

381381
int NET_Send(int s, void *msg, int len, unsigned int flags) {
382-
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
382+
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
383383
}
384384

385385
int NET_SendTo(int s, const void *msg, int len, unsigned int
386386
flags, const struct sockaddr *to, int tolen) {
387-
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
387+
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
388388
}
389389

390390
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
391-
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
391+
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
392392
}
393393

394394
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
395-
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
395+
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE );
396396
}
397397

398398
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
399-
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
399+
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
400400
}
401401

402402
/*

src/java.base/macosx/native/libnet/bsd_close.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -349,58 +349,58 @@ int NET_SocketClose(int fd) {
349349
/************** Basic I/O operations here ***************/
350350

351351
/*
352-
* Macro to perform a blocking IO operation. Restarts
353-
* automatically if interrupted by signal (other than
354-
* our wakeup signal)
352+
* Macro to perform a blocking IO operation.
353+
* If interrupted by signal (other than our wakeup signal), and if RETRY is true,
354+
* then restarts automatically
355355
*/
356-
#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
357-
int ret; \
358-
threadEntry_t self; \
359-
fdEntry_t *fdEntry = getFdEntry(FD); \
360-
if (fdEntry == NULL) { \
361-
errno = EBADF; \
362-
return -1; \
363-
} \
364-
do { \
365-
startOp(fdEntry, &self); \
366-
ret = FUNC; \
367-
endOp(fdEntry, &self); \
368-
} while (ret == -1 && errno == EINTR); \
369-
return ret; \
356+
#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \
357+
int ret; \
358+
threadEntry_t self; \
359+
fdEntry_t *fdEntry = getFdEntry(FD); \
360+
if (fdEntry == NULL) { \
361+
errno = EBADF; \
362+
return -1; \
363+
} \
364+
do { \
365+
startOp(fdEntry, &self); \
366+
ret = FUNC; \
367+
endOp(fdEntry, &self); \
368+
} while ((RETRY) && ret == -1 && errno == EINTR); \
369+
return ret; \
370370
}
371371

372372
int NET_Read(int s, void* buf, size_t len) {
373-
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
373+
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE );
374374
}
375375

376376
int NET_NonBlockingRead(int s, void* buf, size_t len) {
377-
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT));
377+
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE);
378378
}
379379

380380
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
381381
struct sockaddr *from, socklen_t *fromlen) {
382-
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
382+
BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen), JNI_TRUE );
383383
}
384384

385385
int NET_Send(int s, void *msg, int len, unsigned int flags) {
386-
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
386+
BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE );
387387
}
388388

389389
int NET_SendTo(int s, const void *msg, int len, unsigned int
390390
flags, const struct sockaddr *to, int tolen) {
391-
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
391+
BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE );
392392
}
393393

394394
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
395-
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
395+
BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen), JNI_TRUE );
396396
}
397397

398398
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
399-
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
399+
BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE );
400400
}
401401

402402
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
403-
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
403+
BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE );
404404
}
405405

406406
/*
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2023, Alibaba Group Holding Limited. All Rights Reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8312065
27+
* @summary Socket.connect does not timeout as expected when profiling (i.e. keep receiving signal)
28+
* @requires (os.family != "windows")
29+
* @compile NativeThread.java
30+
* @run main/othervm/native/timeout=120 -Djdk.net.usePlainSocketImpl B8312065
31+
*/
32+
33+
import sun.misc.Signal;
34+
35+
import java.net.InetSocketAddress;
36+
import java.net.Socket;
37+
import java.net.SocketTimeoutException;
38+
import java.util.concurrent.TimeUnit;
39+
40+
public class B8312065 {
41+
public static void main(String[] args) throws Exception {
42+
System.loadLibrary("NativeThread");
43+
44+
// Setup SIGPIPE handler
45+
Signal.handle(new Signal("PIPE"), System.out::println);
46+
47+
long osThreadId = NativeThread.getID();
48+
49+
int timeoutMillis = 2000;
50+
int n = 10;
51+
Thread t = new Thread(() -> {
52+
// Send SIGPIPE to the thread every second
53+
for (int i = 0; i < n; i++) {
54+
if (NativeThread.signal(osThreadId, NativeThread.SIGPIPE) != 0) {
55+
System.out.println("Test FAILED: failed to send signal");
56+
System.exit(1);
57+
}
58+
try {
59+
Thread.sleep(1000);
60+
} catch (InterruptedException e) {
61+
System.out.println("Test FAILED: unexpected interrupt");
62+
System.exit(1);
63+
}
64+
}
65+
System.out.println("Test FAILED: Socket.connect blocked " + n + " seconds, " +
66+
"expected around " + timeoutMillis / 1000 + " seconds");
67+
System.exit(1);
68+
});
69+
t.setDaemon(true);
70+
t.start();
71+
72+
long startTime = System.nanoTime();
73+
74+
try {
75+
Socket socket = new Socket();
76+
// There is no good way to mock SocketTimeoutException, just assume 192.168.255.255 is not in use
77+
socket.connect(new InetSocketAddress("192.168.255.255", 8080), timeoutMillis);
78+
} catch (SocketTimeoutException e) {
79+
long duration = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
80+
if (duration >= timeoutMillis) {
81+
System.out.println("Test passed");
82+
} else {
83+
System.out.println("Test FAILED: duration " + duration + " ms, expected >= " + timeoutMillis + " ms");
84+
System.exit(1);
85+
}
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)