Skip to content

Commit 0ff12a6

Browse files
committed
forgot handling of EINTR in accept, the server could hang in rare cases, typically after DDOS attack
1 parent a38a809 commit 0ff12a6

1 file changed

Lines changed: 25 additions & 26 deletions

File tree

src/Async.ml

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,25 +1206,15 @@ let accept_loop (domains : Domain.id Array.t) listens pipes maxc =
12061206
let exception Blocked of int in
12071207
let send_socket sock lsock =
12081208
let index = try Hashtbl.find tbl sock with Not_found -> assert false in
1209+
let (pipe_index, pipe) = get_best () in
12091210
try
1210-
let (pipe_index, pipe) = get_best () in
1211+
Bytes.set_int32_ne pipe_buf 0 (Int32.of_int (Util.file_descr_to_int lsock));
1212+
Bytes.set_int32_ne pipe_buf 4 (Int32.of_int index);
1213+
assert(Util.single_write pipe pipe_buf 0 8 = 8);
12111214
Atomic.incr (nbc pipe_index);
1212-
try
1213-
Bytes.set_int32_ne pipe_buf 0 (Int32.of_int (Util.file_descr_to_int lsock));
1214-
Bytes.set_int32_ne pipe_buf 4 (Int32.of_int index);
1215-
assert(Util.single_write pipe pipe_buf 0 8 = 8);
1216-
with
1217-
| Unix.(Unix_error ((EAGAIN |EWOULDBLOCK), _,_)) ->
1218-
raise (Blocked pipe_index)
1219-
| e ->
1220-
Atomic.decr (nbc pipe_index);
1221-
(try Unix.close lsock with Unix.Unix_error _ -> ());
1222-
raise e
12231215
with
1224-
| Full ->
1225-
(try Unix.close lsock with Unix.Unix_error _ -> ());
1226-
Log.f (Exc 0) (fun k -> k "handler: reject too many clients");
1227-
1216+
| Unix.(Unix_error ((EAGAIN |EWOULDBLOCK), _,_)) ->
1217+
raise (Blocked pipe_index)
12281218
in
12291219
let rec send_sockets = function
12301220
[] -> ()
@@ -1236,24 +1226,33 @@ let accept_loop (domains : Domain.id Array.t) listens pipes maxc =
12361226
| Blocked pipe_index ->
12371227
pendings.(pipe_index) <- List.rev_append all pendings.(pipe_index);
12381228
fun () -> ()
1229+
| Full ->
1230+
(try Unix.close lsock with Unix.Unix_error _ -> ());
1231+
Log.f (Exc 0) (fun k -> k "handler: reject too many clients");
1232+
fun () -> send_sockets rest
12391233
| exn ->
1240-
Log.f (Exc 0) (fun k -> k "unexpected exception in accept loop: %s" (printexn exn));
1234+
(try Unix.close lsock with Unix.Unix_error _ -> ());
1235+
Log.f (Exc 0) (fun k -> k "unexpected exception in send_socket: %s" (printexn exn));
12411236
fun () -> send_sockets rest) ()
12421237
in
1238+
let exception Continue in
12431239
let treat _ sock evt =
12441240
if Polly.Events.(inp land evt <> empty) then
12451241
begin
12461242
try
12471243
while true do
1248-
let lsock, _ =
1249-
try Unix.accept ~cloexec:true sock with
1250-
| Unix.(Unix_error ((EAGAIN |EWOULDBLOCK), _,_)) ->
1251-
raise Exit
1252-
| Unix.Unix_error _ as exn ->
1253-
Log.f (Exc 0) (fun k -> k "unexpected exception in Unix.accept: %s" (printexn exn));
1254-
raise FailHandling
1255-
in
1256-
send_sockets [sock, lsock];
1244+
try
1245+
let lsock, _ =
1246+
try Unix.accept ~cloexec:true sock with
1247+
| Unix.(Unix_error(EINTR,_,_)) -> raise Continue
1248+
| Unix.(Unix_error ((EAGAIN |EWOULDBLOCK), _,_)) ->
1249+
raise Exit
1250+
| Unix.Unix_error _ as exn ->
1251+
Log.f (Exc 0) (fun k -> k "unexpected exception in Unix.accept: %s" (printexn exn));
1252+
raise FailHandling
1253+
in
1254+
send_sockets [sock, lsock];
1255+
with Continue -> ()
12571256
done
12581257
with Exit -> ()
12591258
end

0 commit comments

Comments
 (0)