Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --wait stdio #5188

Merged
merged 2 commits into from
May 1, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 83 additions & 46 deletions src/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -683,17 +683,9 @@ let rec process_params create pl =
) in
loop [] pl

and wait_loop boot_com host port =
let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
(try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ());
(try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port));
Unix.listen sock 10;
and wait_loop verbose accept =
Sys.catch_break false;
let verbose = boot_com.verbose in
let has_parse_error = ref false in
if verbose then print_endline ("Waiting on " ^ host ^ ":" ^ string_of_int port);
let bufsize = 1024 in
let tmp = String.create bufsize in
let cache = {
c_haxelib = Hashtbl.create 0;
c_files = Hashtbl.create 0;
Expand Down Expand Up @@ -840,33 +832,8 @@ and wait_loop boot_com host port =
);
let run_count = ref 0 in
while true do
let sin, _ = Unix.accept sock in
let read, write, close = accept() in
let t0 = get_time() in
Unix.set_nonblock sin;
if verbose then print_endline "Client connected";
let b = Buffer.create 0 in
let rec read_loop count =
try
let r = Unix.recv sin tmp 0 bufsize [] in
if r = 0 then
failwith "Incomplete request"
else begin
if verbose then Printf.printf "Reading %d bytes\n" r;
Buffer.add_substring b tmp 0 r;
if tmp.[r-1] = '\000' then
Buffer.sub b 0 (Buffer.length b - 1)
else
read_loop 0
end
with Unix.Unix_error((Unix.EWOULDBLOCK|Unix.EAGAIN),_,_) ->
if count = 100 then
failwith "Aborting inactive connection"
else begin
if verbose then print_endline "Waiting for data...";
ignore(Unix.select [] [] [] 0.05); (* wait a bit *)
read_loop (count + 1);
end
in
let rec cache_context com =
if com.display = DMNone then begin
List.iter cache_module com.modules;
Expand All @@ -881,8 +848,8 @@ and wait_loop boot_com host port =
ctx.flush <- (fun() ->
incr compilation_step;
compilation_mark := !mark_loop;
List.iter (fun s -> ssend sin (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages);
if ctx.has_error then ssend sin "\x02\n" else cache_context ctx.com;
List.iter (fun s -> write (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages);
if ctx.has_error then write "\x02\n" else cache_context ctx.com;
);
ctx.setup <- (fun() ->
if verbose then begin
Expand All @@ -900,11 +867,11 @@ and wait_loop boot_com host port =
Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- true) cache.c_modules
end
);
ctx.com.print <- (fun str -> ssend sin ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit str "\n") ^ "\n"));
ctx.com.print <- (fun str -> write ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit str "\n") ^ "\n"));
ctx
in
(try
let s = (read_loop 0) in
let s = read() in
let hxml =
try
let idx = String.index s '\001' in
Expand All @@ -914,7 +881,6 @@ and wait_loop boot_com host port =
s
in
let data = parse_hxml_data hxml in
Unix.clear_nonblock sin;
if verbose then print_endline ("Processing Arguments [" ^ String.concat "," data ^ "]");
(try
Common.display_default := DMNone;
Expand All @@ -933,11 +899,11 @@ and wait_loop boot_com host port =
start_time := get_time();
process_params create data;
close_times();
if !measure_times then report_times (fun s -> ssend sin (s ^ "\n"))
if !measure_times then report_times (fun s -> write (s ^ "\n"))
with
| Completion str ->
if verbose then print_endline ("Completion Response =\n" ^ str);
ssend sin str
write str
| Arg.Bad msg ->
prerr_endline ("Error: " ^ msg);
);
Expand All @@ -950,10 +916,10 @@ and wait_loop boot_com host port =
| e ->
let estr = Printexc.to_string e in
if verbose then print_endline ("Uncaught Error : " ^ estr);
(try ssend sin estr with _ -> ());
(try write estr with _ -> ());
if is_debug_run() then print_endline (Printexc.get_backtrace());
);
Unix.close sin;
close();
current_stdin := None;
(* prevent too much fragmentation by doing some compactions every X run *)
incr run_count;
Expand All @@ -968,6 +934,70 @@ and wait_loop boot_com host port =
end else Gc.minor();
done

and init_wait_stdio() =
set_binary_mode_in stdin true;
set_binary_mode_out stderr true;

let chin = IO.input_channel stdin in
let cherr = IO.output_channel stderr in

let berr = Buffer.create 0 in
let read = fun () ->
let len = IO.read_i32 chin in
IO.really_nread chin len
in
let write = Buffer.add_string berr in
let close = fun() ->
IO.write_i32 cherr (Buffer.length berr);
IO.nwrite cherr (Buffer.contents berr);
IO.flush cherr
in
fun() ->
Buffer.clear berr;
read, write, close

and init_wait_socket verbose host port =
let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
(try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ());
(try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port));
if verbose then print_endline ("Waiting on " ^ host ^ ":" ^ string_of_int port);
Unix.listen sock 10;
let bufsize = 1024 in
let tmp = String.create bufsize in
let accept() = (
let sin, _ = Unix.accept sock in
Unix.set_nonblock sin;
if verbose then print_endline "Client connected";
let b = Buffer.create 0 in
let rec read_loop count =
try
let r = Unix.recv sin tmp 0 bufsize [] in
if r = 0 then
failwith "Incomplete request"
else begin
if verbose then Printf.printf "Reading %d bytes\n" r;
Buffer.add_substring b tmp 0 r;
if tmp.[r-1] = '\000' then
Buffer.sub b 0 (Buffer.length b - 1)
else
read_loop 0
end
with Unix.Unix_error((Unix.EWOULDBLOCK|Unix.EAGAIN),_,_) ->
if count = 100 then
failwith "Aborting inactive connection"
else begin
if verbose then print_endline "Waiting for data...";
ignore(Unix.select [] [] [] 0.05); (* wait a bit *)
read_loop (count + 1);
end
in
let read = fun() -> (let s = read_loop 0 in Unix.clear_nonblock sin; s) in
let write = ssend sin in
let close() = Unix.close sin in
read, write, close
) in
accept

and do_connect host port args =
let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
(try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port));
Expand Down Expand Up @@ -1338,8 +1368,15 @@ try
evals := s :: !evals;
), " : evaluates argument as Haxe module code");
("--wait", Arg.String (fun hp ->
let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
wait_loop com host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port"))
let accept = match hp with
| "stdio" ->
init_wait_stdio()
| _ ->
let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
let port = try int_of_string port with _ -> raise (Arg.Bad "Invalid port") in
init_wait_socket com.verbose host port
in
wait_loop com.verbose accept
),"<[host:]port> : wait on the given port for commands to run)");
("--connect",Arg.String (fun _ ->
assert false
Expand Down