aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLukas Larsson <lukas@erlang-solutions.com>2011-12-07 14:46:26 +0100
committerLukas Larsson <lukas@erlang-solutions.com>2011-12-07 19:19:17 +0100
commit1137c0a08b25ab5e38286260f0b7c51ba015afbb (patch)
tree4258119045dc70037e41fd55e16cdd55724c53a9 /lib
parentf34a89e0c0cc92226d5fe3fb257c62251068392b (diff)
downloadotp-1137c0a08b25ab5e38286260f0b7c51ba015afbb.tar.gz
otp-1137c0a08b25ab5e38286260f0b7c51ba015afbb.tar.bz2
otp-1137c0a08b25ab5e38286260f0b7c51ba015afbb.zip
Return {error,closed} from sendfile if closed
If the socket is closed by the remote end, sendfile now returns {error,closed}.
Diffstat (limited to 'lib')
-rw-r--r--lib/kernel/src/file.erl6
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl41
2 files changed, 43 insertions, 4 deletions
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 0b0f91d86a..a3c0e7da26 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1124,7 +1124,8 @@ change_time(Name, Atime, Mtime)
-define(MAX_CHUNK_SIZE, (1 bsl 20)*20). %% 20 MB, has to fit in primary memory
-spec sendfile(RawFile, Socket, Offset, Bytes, Opts) ->
- {'ok', non_neg_integer()} | {'error', inet:posix() | badarg | not_owner} when
+ {'ok', non_neg_integer()} | {'error', inet:posix() |
+ closed | badarg | not_owner} when
RawFile :: file:fd(),
Socket :: inet:socket(),
Offset :: non_neg_integer(),
@@ -1149,7 +1150,8 @@ sendfile(File, Sock, Offset, Bytes, Opts) ->
%% sendfile/2
-spec sendfile(Filename, Socket) ->
- {'ok', non_neg_integer()} | {'error', inet:posix() | badarg | not_owner}
+ {'ok', non_neg_integer()} | {'error', inet:posix() |
+ closed | badarg | not_owner}
when Filename :: file:name(),
Socket :: inet:socket().
sendfile(Filename, Sock) ->
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
index 4a6cd604e0..483290b91a 100644
--- a/lib/kernel/test/sendfile_SUITE.erl
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -33,6 +33,7 @@ all() ->
,t_sendfile_recvafter
,t_sendfile_sendduring
,t_sendfile_recvduring
+ ,t_sendfile_closeduring
].
init_per_suite(Config) ->
@@ -212,19 +213,52 @@ t_sendfile_recvduring(Config) ->
ok = sendfile_send({127,0,0,1}, Send, 0).
+t_sendfile_closeduring(Config) ->
+ Filename = proplists:get_value(big_file, Config),
+
+ Send = fun(Sock,SFServPid) ->
+ spawn_link(fun() ->
+ timer:sleep(50),
+ SFServPid ! stop
+ end),
+ case erlang:system_info(thread_pool_size) of
+ 0 ->
+ {error, closed} = file:sendfile(Filename, Sock);
+ _Else ->
+ %% This can return how much has been sent or
+ %% {error,closed} depending on OS.
+ %% How much is sent impossible to know as
+ %% the socket was closed mid sendfile
+ case file:sendfile(Filename, Sock) of
+ {error, closed} ->
+ ok;
+ {ok, Size} when is_integer(Size) ->
+ ok
+ end
+ end,
+ -1
+ end,
+
+ ok = sendfile_send({127,0,0,1}, Send, 0).
+
%% Generic sendfile server code
sendfile_send(Send) ->
sendfile_send({127,0,0,1},Send).
sendfile_send(Host, Send) ->
sendfile_send(Host, Send, []).
sendfile_send(Host, Send, Orig) ->
- spawn_link(?MODULE, sendfile_server, [self(), Orig]),
+ SFServer = spawn_link(?MODULE, sendfile_server, [self(), Orig]),
receive
{server, Port} ->
{ok, Sock} = gen_tcp:connect(Host, Port,
[binary,{packet,0},
{active,false}]),
- Data = Send(Sock),
+ Data = case proplists:get_value(arity,erlang:fun_info(Send)) of
+ 1 ->
+ Send(Sock);
+ 2 ->
+ Send(Sock, SFServer)
+ end,
ok = gen_tcp:close(Sock),
receive
{ok, Bin} ->
@@ -247,6 +281,9 @@ sendfile_server(ClientPid, Orig) ->
-define(SENDFILE_TIMEOUT, 10000).
sendfile_do_recv(Sock, Bs) ->
receive
+ stop when Bs /= 0,is_integer(Bs) ->
+ gen_tcp:close(Sock),
+ {ok, -1};
{tcp, Sock, B} ->
case binary:match(B,<<1>>) of
nomatch when is_list(Bs) ->