gen_tcp:send and file:sendfile
Slava Yurin <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.bugs |
|---|---|
| Message-ID | <[email protected]> |
Hi all.
I have error behavior of gen_tcp:send/2 + file:sendfile/5.
If data for send falls into buffer in port and happen file:sendfile/5 call, then
buffer not flushed and data from file send. After that any call gen_tcp:send/2
only append data to buffer and not send anything. And if not set send_timeout
option gen_tcp:send will hang after exceed size of buffer. This is my guess.
I attach test file and log of it usage.
Have reproducible error only when [{delay_send, true}, {nodelay, false}], but in
real usage see same behavior without this options. Can't reproduce it on
localhost and 1 file.
_______________________________________________
erlang-bugs mailing list
[email protected]
http://erlang.org/mailman/listinfo/erlang-bugs
send_file_test.erl
(application/octet-stream, 1.2 KB) - not displayed
shell1.log
(text/plain, 4.2 KB)
v.yurin@hell:~$ uname -a
Linux hell 3.17.3-1-ARCH #1 SMP PREEMPT Fri Nov 14 23:13:48 CET 2014 x86_64 GNU/Linux
v.yurin@hell:~/test$ erl
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.2 (abort with ^G)
1> L = send_file_test:start().
Listen on 59690
#Port<0.563>
2> send_file_test:one_client(L, [], 1).
ok
Send file 1
3> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}], 1).
ok
Send file 1
4> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}, {send_timeout, 1000}], 200).
ok
Send file 200
Send file 199
Send file 198
Send file 197
Send file 196
Send file 195
Send file 194
Send file 193
Send file 192
Send file 191
Send file 190
Send file 189
Send file 188
Send file 187
Send file 186
Send file 185
Send file 184
Send file 183
Send file 182
Send file 181
Send file 180
Send file 179
Send file 178
Send file 177
Send file 176
Send file 175
Send file 174
Send file 173
Send file 172
Send file 171
Send file 170
Send file 169
Send file 168
Send file 167
Send file 166
Send file 165
Send file 164
Send file 163
Send file 162
Send file 161
Send file 160
Send file 159
Send file 158
Send file 157
Send file 156
Send file 155
Send file 154
Send file 153
Send file 152
Send file 151
Send file 150
Send file 149
Send file 148
Send file 147
Send file 146
Send file 145
Send file 144
Send file 143
Send file 142
Send file 141
Send file 140
Send file 139
Send file 138
Send file 137
Send file 136
Send file 135
Send file 134
Send file 133
Send file 132
Send file 131
Send file 130
Send file 129
Send file 128
Send file 127
Send file 126
Send file 125
Send file 124
Send file 123
Send file 122
Send file 121
Send file 120
Send file 119
Send file 118
Send file 117
Send file 116
Send file 115
Send file 114
Send file 113
Send file 112
Send file 111
Send file 110
Send file 109
Send file 108
Send file 107
Send file 106
Send file 105
Send file 104
Send file 103
Send file 102
Send file 101
Send file 100
Send file 99
Send file 98
Send file 97
Send file 96
Send file 95
Send file 94
Send file 93
Send file 92
Send file 91
Send file 90
Send file 89
Send file 88
Send file 87
Send file 86
Send file 85
Send file 84
Send file 83
5>
=ERROR REPORT==== 10-Dec-2014::12:45:28 ===
Error in process <0.40.0> with exit value: {{badmatch,{error,timeout}},[{send_file_test,loop,3,[{file,"send_file_test.erl"},{line,37}]}]}
5> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}], 200). ok
Send file 200
Send file 199
Send file 198
Send file 197
Send file 196
Send file 195
Send file 194
Send file 193
Send file 192
Send file 191
Send file 190
Send file 189
Send file 188
Send file 187
Send file 186
Send file 185
Send file 184
Send file 183
Send file 182
Send file 181
Send file 180
Send file 179
Send file 178
Send file 177
Send file 176
Send file 175
Send file 174
Send file 173
Send file 172
Send file 171
Send file 170
Send file 169
Send file 168
Send file 167
Send file 166
Send file 165
Send file 164
Send file 163
Send file 162
Send file 161
Send file 160
Send file 159
Send file 158
Send file 157
Send file 156
Send file 155
Send file 154
Send file 153
Send file 152
Send file 151
Send file 150
Send file 149
Send file 148
Send file 147
Send file 146
Send file 145
Send file 144
Send file 143
Send file 142
Send file 141
Send file 140
Send file 139
Send file 138
Send file 137
Send file 136
Send file 135
Send file 134
Send file 133
Send file 132
Send file 131
Send file 130
Send file 129
Send file 128
Send file 127
Send file 126
Send file 125
Send file 124
Send file 123
Send file 122
Send file 121
Send file 120
Send file 119
Send file 118
Send file 117
Send file 116
Send file 115
Send file 114
Send file 113
Send file 112
Send file 111
Send file 110
Send file 109
Send file 108
Send file 107
Send file 106
Send file 105
Send file 104
Send file 103
Send file 102
Send file 101
Send file 100
Send file 99
Send file 98
Send file 97
Send file 96
Send file 95
Send file 94
Send file 93
Send file 92
Send file 91
Send file 90
Send file 89
Send file 88
Send file 87
Send file 86
Send file 85
Send file 84
Send file 83
6> now().
{1418,194038,215600}
7> now().
{1418,194077,282560}
8> "send hang ...".
shell2.log
(text/plain, 5.4 KB)
v.yurin@hell:~$ telnet 127.0.0.1 59690 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. start Some data before file File 1: %% @author Slava Yurin <[email protected]> %% @doc Test Sendfile -module(send_file_test). -export([one_client/3]). -export([start/0]). start() -> {ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]), {ok, Port} = inet:port(Listen), io:format("Listen on ~p~n", [Port]), Listen. one_client(Listen, Opt, FileCount) -> {ok, Client} = gen_tcp:accept(Listen), %Opt = [{delay_send, false}, {nodelay, true}], %Opt = [{delay_send, true}, {nodelay, false}], ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]), Pid = spawn(fun() -> loop(Client, FileCount) end), ok = gen_tcp:controlling_process(Client, Pid), Pid ! start, ok. loop(Client, FileCount) -> receive start -> ok end, {ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0), {ok, FD} = file:open("send_file_test.erl", [raw, read, binary]), loop(Client, FD, FileCount). loop(_, _, 0) -> ok; loop(Client, FD, Pos) -> io:format("Send file ~p~n", [Pos]), ok = gen_tcp:send(Client, ["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]), {ok, _} = file:sendfile(FD, Client, 0, 0, []), ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]), loop(Client, FD, Pos - 1). File 1 end Some data after file Connection closed by foreign host. v.yurin@hell:~$ telnet 127.0.0.1 59690 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. start %% @author Slava Yurin <[email protected]> %% @doc Test Sendfile -module(send_file_test). -export([one_client/3]). -export([start/0]). start() -> {ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]), {ok, Port} = inet:port(Listen), io:format("Listen on ~p~n", [Port]), Listen. one_client(Listen, Opt, FileCount) -> {ok, Client} = gen_tcp:accept(Listen), %Opt = [{delay_send, false}, {nodelay, true}], %Opt = [{delay_send, true}, {nodelay, false}], ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]), Pid = spawn(fun() -> loop(Client, FileCount) end), ok = gen_tcp:controlling_process(Client, Pid), Pid ! start, ok. loop(Client, FileCount) -> receive start -> ok end, {ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0), {ok, FD} = file:open("send_file_test.erl", [raw, read, binary]), loop(Client, FD, FileCount). loop(_, _, 0) -> ok; loop(Client, FD, Pos) -> io:format("Send file ~p~n", [Pos]), ok = gen_tcp:send(Client, ["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]), {ok, _} = file:sendfile(FD, Client, 0, 0, []), ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]), loop(Client, FD, Pos - 1). Connection closed by foreign host. v.yurin@hell:~$ telnet 127.0.0.1 59690 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. start [ ... skip ... ] %% @author Slava Yurin <[email protected]> %% @doc Test Sendfile -module(send_file_test). -export([one_client/3]). -export([start/0]). start() -> {ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]), {ok, Port} = inet:port(Listen), io:format("Listen on ~p~n", [Port]), Listen. one_client(Listen, Opt, FileCount) -> {ok, Client} = gen_tcp:accept(Listen), %Opt = [{delay_send, false}, {nodelay, true}], %Opt = [{delay_send, true}, {nodelay, false}], ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]), Pid = spawn(fun() -> loop(Client, FileCount) end), ok = gen_tcp:controlling_process(Client, Pid), Pid ! start, ok. loop(Client, FileCount) -> receive start -> ok end, {ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0), {ok, FD} = file:open("send_file_test.erl", [raw, read, binary]), loop(Client, FD, FileCount). loop(_, _, 0) -> ok; loop(Client, FD, Pos) -> io:format("Send file ~p~n", [Pos]), ok = gen_tcp:send(Client, ["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]), {ok, _} = file:sendfile(FD, Client, 0, 0, []), ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]), loop(Client, FD, Pos - 1). Connection closed by foreign host. v.yurin@hell:~$ telnet 127.0.0.1 59690 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. start [ ... skip ... ] %% @author Slava Yurin <[email protected]> %% @doc Test Sendfile -module(send_file_test). -export([one_client/3]). -export([start/0]). start() -> {ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]), {ok, Port} = inet:port(Listen), io:format("Listen on ~p~n", [Port]), Listen. one_client(Listen, Opt, FileCount) -> {ok, Client} = gen_tcp:accept(Listen), %Opt = [{delay_send, false}, {nodelay, true}], %Opt = [{delay_send, true}, {nodelay, false}], ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]), Pid = spawn(fun() -> loop(Client, FileCount) end), ok = gen_tcp:controlling_process(Client, Pid), Pid ! start, ok. loop(Client, FileCount) -> receive start -> ok end, {ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0), {ok, FD} = file:open("send_file_test.erl", [raw, read, binary]), loop(Client, FD, FileCount). loop(_, _, 0) -> ok; loop(Client, FD, Pos) -> io:format("Send file ~p~n", [Pos]), ok = gen_tcp:send(Client, ["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]), {ok, _} = file:sendfile(FD, Client, 0, 0, []), ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]), loop(Client, FD, Pos - 1).