Skip to content

Commit 84ef22b

Browse files
committed
Enabling nagle, and adding Linux only TCP flush
Fixing EINTR handling during socket error handling Using epoll_pwait2 if possible
1 parent a60f664 commit 84ef22b

File tree

4 files changed

+42
-34
lines changed

4 files changed

+42
-34
lines changed

ext/socket/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ ENDIF()
1515
# Windows - WSAPoll
1616
IF (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
1717
SET(SELECTOR_SOURCE selector-epoll.c)
18+
CHECK_FUNCTION_EXISTS(epoll_pwait2 HAVE_EPOLL_PWAIT2)
19+
IF (HAVE_EPOLL_PWAIT2)
20+
MESSAGE(STATUS "Using epoll_wait2")
21+
ADD_DEFINITIONS(-DHAVE_EPOLL_PWAIT2)
22+
ENDIF()
1823
ELSEIF(WIN32)
1924
SET(SELECTOR_SOURCE selector-win.c)
2025
ELSE()

ext/socket/sagittarius-socket.c

+28-30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* sagittarius-socket.c -*- mode:c; coding:utf-8; -*-
22
*
3-
* Copyright (c) 2010-2016 Takashi Kato <ktakashi@ymail.com>
3+
* Copyright (c) 2010-2025 Takashi Kato <ktakashi@ymail.com>
44
*
55
* Redistribution and use in source and binary forms, with or without
66
* modification, are permitted provided that the following conditions
@@ -500,13 +500,15 @@ SgObject Sg_CreateSocket(int family, int socktype, int protocol)
500500
return make_socket_inner(fd);
501501
}
502502

503-
static void disable_nagle(SOCKET fd)
503+
static void flush_tcp(SOCKET fd)
504504
{
505505
#ifdef TCP_NODELAY
506-
const int value = 1;
507-
/* we ignore the return value here, since this is merely performance
508-
optimisation */
509-
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(int));
506+
int value = 1;
507+
/* we ignore the return value here, since this is merely performance
508+
optimisation */
509+
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(int));
510+
value = 0;
511+
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(int));
510512
#endif
511513
}
512514

@@ -541,8 +543,6 @@ SgObject Sg_SocketConnect(SgSocket *socket, SgAddrinfo* addrinfo,
541543
goto err;
542544
}
543545
}
544-
545-
disable_nagle(socket->socket);
546546
socket->type = SG_SOCKET_CLIENT;
547547
socket->address = SG_SOCKADDR(ai_addr(addrinfo));
548548
socket->node = addrinfo->node;
@@ -708,29 +708,27 @@ SgObject Sg_SocketGetopt(SgSocket *socket, int level, int name, int rsize)
708708
#endif
709709

710710
#define handleError(who, socket, r) \
711-
do { \
712-
if ((r) < 0) { \
713-
int e = last_error; \
714-
socket->lastError = e; \
715-
switch (e) { \
716-
case EINTR: \
717-
continue; \
718-
case EPIPE: \
719-
if (flags & MSG_NOSIGNAL) { \
720-
return 0; \
721-
} \
722-
break; \
723-
case NON_BLOCKING_CASE: \
724-
case ETIMEDOUT:/* Windows, maybe we should raise an error here*/ \
725-
/* most probably non-blocking socket */ \
726-
return (r); \
711+
if ((r) < 0) { \
712+
int e = last_error; \
713+
socket->lastError = e; \
714+
switch (e) { \
715+
case EINTR: \
716+
continue; \
717+
case EPIPE: \
718+
if (flags & MSG_NOSIGNAL) { \
719+
return 0; \
727720
} \
728-
raise_socket_error(SG_INTERN(who), \
729-
Sg_GetLastErrorMessageWithErrorCode(e), \
730-
Sg_MakeConditionSocket(socket), \
731-
SG_LIST1(SG_MAKE_INT(e))); \
721+
break; \
722+
case NON_BLOCKING_CASE: \
723+
case ETIMEDOUT:/* Windows, maybe we should raise an error here*/ \
724+
/* most probably non-blocking socket */ \
725+
return (r); \
732726
} \
733-
} while (0)
727+
raise_socket_error(SG_INTERN(who), \
728+
Sg_GetLastErrorMessageWithErrorCode(e), \
729+
Sg_MakeConditionSocket(socket), \
730+
SG_LIST1(SG_MAKE_INT(e))); \
731+
} \
734732

735733
long Sg_SocketReceive(SgSocket *socket, uint8_t *data, long size, int flags)
736734
{
@@ -776,6 +774,7 @@ long Sg_SocketSend(SgSocket *socket, uint8_t *data, long size, int flags)
776774
data += ret;
777775
size -= ret;
778776
}
777+
flush_tcp(socket->socket);
779778
return sizeSent;
780779
}
781780

@@ -870,7 +869,6 @@ SgObject Sg_SocketAccept(SgSocket *socket)
870869
break;
871870
}
872871
}
873-
disable_nagle(fd);
874872
return make_socket(fd, SG_SOCKET_SERVER,
875873
make_sockaddr(addrlen, (struct sockaddr *)&addr, TRUE));
876874
}

ext/socket/sagittarius/socket.scm

-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@
230230
(cond ((and (zero? ms) (zero? ns)) "") ;; no timeout
231231
((zero? ms) (format ", timeout: ~a" t)) ;; less then millis
232232
(else (format ", timeout: ~ams" ms)))))
233-
234233
(let ((to (socket-get-read-timeout sock)))
235234
(raise (condition (make-socket-read-timeout-error sock to)
236235
(make-who-condition who)

ext/socket/selector-epoll.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,17 @@ static SgObject wait_selector(unix_context_t *ctx, int nsock,
7676
int *err)
7777
{
7878
int n = nsock + 1, i, c;
79-
long millis = -1;
8079
SgObject r = SG_NIL, cp;
8180
struct epoll_event *evm, ev;
8281

82+
#ifndef HAVE_EPOLL_PWAIT2
83+
long millis = -1;
8384
if (sp) {
8485
millis = sp->tv_sec * 1000;
8586
millis += sp->tv_nsec / 1000000;
8687
}
88+
#endif
89+
8790
SG_FOR_EACH(cp, sockets) {
8891
add_socket_ctx(ctx, SG_CAR(cp));
8992
}
@@ -92,7 +95,11 @@ static SgObject wait_selector(unix_context_t *ctx, int nsock,
9295
epoll_ctl(ctx->fd, EPOLL_CTL_ADD, ctx->stop_fd, &ev);
9396

9497
evm = SG_NEW_ATOMIC2(struct epoll_event *, n * sizeof(struct epoll_event));
98+
#ifndef HAVE_EPOLL_PWAIT2
9599
c = epoll_wait(ctx->fd, evm, n, millis);
100+
#else
101+
c = epoll_pwait2(ctx->fd, evm, n, sp, NULL);
102+
#endif
96103
/*
97104
EINTR The call was interrupted by a signal handler before either
98105
(1) any of the requested events occurred or (2) the
@@ -108,9 +115,8 @@ static SgObject wait_selector(unix_context_t *ctx, int nsock,
108115
for (i = 0; i < c; i++) {
109116
if (SG_FALSEP(evm[i].data.ptr)) {
110117
interrupted_unix_stop(ctx);
111-
} else if (SG_PAIRP(evm[i].data.ptr) && evm[i].events == EPOLLIN) {
118+
} else if (evm[i].events & EPOLLIN) {
112119
SgObject slot = SG_OBJ(evm[i].data.ptr);
113-
/* SgSocket *sock = SG_SOCKET(SG_CAR(slot)); */
114120
r = Sg_Cons(slot, r);
115121
}
116122
}

0 commit comments

Comments
 (0)