summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2021-05-05 13:45:56 +0200
committerErlang/OTP <otp@erlang.org>2021-05-05 13:45:56 +0200
commit12cd6598b3c924d6ef11c96d738fb92c8ceec990 (patch)
treefd7e302122bdd2be618689372b055159b0881927
parentd690f087968fb5fffe362c6da267c9cfd3270fb1 (diff)
parente867f51f9ed482daa5c4c525ab9c25111eb20642 (diff)
downloaderlang-12cd6598b3c924d6ef11c96d738fb92c8ceec990.tar.gz
Merge branch 'lukas/erl_interface/send-inf-tmo-fix/OTP-17358' into maint-21
* lukas/erl_interface/send-inf-tmo-fix/OTP-17358: ei: Correctly check timeout value vs EI_SCLBK_INF_TMO
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml2
-rw-r--r--lib/erl_interface/src/misc/ei_portio.c26
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl18
3 files changed, 34 insertions, 12 deletions
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index 2dd0a285fe..8402787c67 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -1073,7 +1073,7 @@ self->num = fd;
</func>
<func>
- <name since=""><ret>int</ret><nametext>ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf, int len)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf, int len, unsigned timeout_ms)</nametext></name>
<fsummary>Obsolete function to send a message to a registered name with
time-out.</fsummary>
<desc>
diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c
index bccc86c1b1..a076e1ef7d 100644
--- a/lib/erl_interface/src/misc/ei_portio.c
+++ b/lib/erl_interface/src/misc/ei_portio.c
@@ -404,6 +404,12 @@ static int writev_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
do {
error = cbs->writev(ctx, (const void *) iov, iovcnt, len, ms);
} while (error == EINTR);
+
+ /* It should not be possible for writev_ctx_t__ to return EAGAIN,
+ because when the fd is set in non-blocking we always do a select on
+ the fd before trying to write. And if we do not do the select the fd
+ is always in blocking mode. */
+
return error;
}
@@ -417,7 +423,8 @@ int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
struct iovec *current_iov;
int current_iovcnt;
int fd, error;
- int basic;
+ int non_blocking = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) &&
+ ms != EI_SCLBK_INF_TMO;
if (!cbs->writev)
return ENOTSUP;
@@ -426,12 +433,10 @@ int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
if (error)
return error;
- basic = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL);
-
for (sum = 0, i = 0; i < iovcnt; ++i) {
sum += iov[i].iov_len;
}
- if (basic && ms != 0U) {
+ if (non_blocking) {
SET_NONBLOCKING(fd);
}
current_iovcnt = iovcnt;
@@ -442,7 +447,7 @@ int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
error = writev_ctx_t__(cbs, ctx, current_iov, current_iovcnt, &i, ms);
if (error) {
*len = done;
- if (ms != 0U) {
+ if (non_blocking) {
SET_BLOCKING(fd);
}
if (iov_base != NULL) {
@@ -478,7 +483,7 @@ int ei_writev_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx,
break;
}
}
- if (basic && ms != 0U) {
+ if (non_blocking) {
SET_BLOCKING(fd);
}
if (iov_base != NULL) {
@@ -752,9 +757,10 @@ int ei_read_fill_ctx__(ei_socket_callbacks *cbs, void *ctx, char* buf, ssize_t *
int ei_write_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const char *buf, ssize_t *len, unsigned ms)
{
ssize_t tot = *len, done = 0;
- int error, fd = -1, basic = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL);
+ int error, fd = -1, non_blocking = !(cbs->flags & EI_SCLBK_FLG_FULL_IMPL) &&
+ ms != EI_SCLBK_INF_TMO;
- if (basic && ms != 0U) {
+ if (non_blocking) {
error = EI_GET_FD__(cbs, ctx, &fd);
if (error)
return error;
@@ -765,14 +771,14 @@ int ei_write_fill_ctx_t__(ei_socket_callbacks *cbs, void *ctx, const char *buf,
error = write_ctx_t__(cbs, ctx, buf+done, &write_len, ms);
if (error) {
*len = done;
- if (basic && ms != 0U) {
+ if (non_blocking) {
SET_BLOCKING(fd);
}
return error;
}
done += write_len;
} while (done < tot);
- if (basic && ms != 0U) {
+ if (non_blocking) {
SET_BLOCKING(fd);
}
*len = done;
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 75b6bf18da..a219d35ed6 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -28,6 +28,7 @@
init_per_testcase/2,
ei_send/1,
ei_reg_send/1,
+ ei_reg_send_large/1,
ei_format_pid/1,
ei_rpc/1,
rpc_test/1,
@@ -42,7 +43,7 @@ suite() ->
{timetrap, {seconds, 30}}].
all() ->
- [ei_send, ei_reg_send, ei_rpc, ei_format_pid, ei_send_funs,
+ [ei_send, ei_reg_send, ei_reg_send_large, ei_rpc, ei_format_pid, ei_send_funs,
ei_threaded_send, ei_set_get_tracelevel].
init_per_testcase(Case, Config) ->
@@ -105,6 +106,21 @@ ei_reg_send(Config) when is_list(Config) ->
runner:recv_eot(P),
ok.
+ei_reg_send_large(Config) when is_list(Config) ->
+ P = runner:start(Config, ?interpret),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
+ {ok,Fd} = ei_connect(P, node()),
+
+ ARegName = a_strange_registred_name,
+ register(ARegName, self()),
+ ok = ei_reg_send(P, Fd, ARegName, AMsg={another,[strange],message,
+ <<0:(32*1024*1024*8)>>}),
+ receive AMsg -> ok end,
+
+ runner:send_eot(P),
+ runner:recv_eot(P),
+ ok.
+
ei_threaded_send(Config) when is_list(Config) ->
Einode = filename:join(proplists:get_value(data_dir, Config), "einode"),
N = 15,