# # # add_dir "tests/netsync_stop_server" # # add_file "tests/netsync_stop_server/__driver__.lua" # content [a586b3c09eaac9938b748ee897c161ff8996a375] # # patch "monotone.texi" # from [60e0e6b916105563524335051f9789e1d77e57e7] # to [a2edd01e7932280ff956deeb57de9daa33e8e4b8] # # patch "netsync.cc" # from [8903949241946020ebadb6f0ade5b900ef95a66a] # to [1a7261f49941cb4f55849fe0ba087046b01ee84e] # # patch "network/reactor.cc" # from [fa961bc15a1d0a1a6df66d04b2a57ca63941af34] # to [a90cee5442d3c77d8082d7bb91d4d23170bf25fb] # # patch "tests/common/netsync.lua" # from [f15a83e9fa031b64b790543973c10f78fcedfe57] # to [fc5f1471dd9610885b0e681f41eab2c349ff482a] # ============================================================ --- tests/netsync_stop_server/__driver__.lua a586b3c09eaac9938b748ee897c161ff8996a375 +++ tests/netsync_stop_server/__driver__.lua a586b3c09eaac9938b748ee897c161ff8996a375 @@ -0,0 +1,11 @@ +include("common/netsync.lua") +mtn_setup() +netsync.setup() + +the_hook = "function note_netsync_end() server_set_listening(false) io.write('x') io.flush() end" +writefile("my_hooks.lua", the_hook) + +srv = netsync.start({"--rcfile=my_hooks.lua"}) +srv:pull("*") + +check(srv:wait(1)) ============================================================ --- monotone.texi 60e0e6b916105563524335051f9789e1d77e57e7 +++ monotone.texi a2edd01e7932280ff956deeb57de9daa33e8e4b8 @@ -11377,6 +11377,13 @@ @section Additional Lua Functions When called by a monotone instance which is not running the @option{serve} command, this function has no effect. address@hidden server_set_listening(@var{boolean}) + +If the argument is @var{false}, make the server not listen for incoming +connections, and exit when all existing connections have closed. + +If the argument is @var{true}, cancel an earlier call with @var{false} given. + @item sleep(@var{seconds}) Makes the calling process sleep for the specified number of seconds. ============================================================ --- netsync.cc 8903949241946020ebadb6f0ade5b900ef95a66a +++ netsync.cc 1a7261f49941cb4f55849fe0ba087046b01ee84e @@ -256,6 +256,25 @@ session_from_server_sync_item(app_state } } +enum listener_status { listener_listening, listener_not_listening }; +listener_status desired_listener_status; +LUAEXT(server_set_listening, ) +{ + if (lua_isboolean(LS, 1)) + { + bool want_listen = lua_toboolean(LS, 1); + if (want_listen) + desired_listener_status = listener_listening; + else + desired_listener_status = listener_not_listening; + return 0; + } + else + { + return luaL_error(LS, "bad argument (not a boolean)"); + } +} + static void serve_connections(app_state & app, options & opts, @@ -278,6 +297,8 @@ serve_connections(app_state & app, react, role, addresses, guard, use_ipv6)); react.add(listen, *guard); + desired_listener_status = listener_listening; + listener_status actual_listener_status = listener_listening; while (true) { @@ -304,11 +325,33 @@ serve_connections(app_state & app, } } + if (desired_listener_status != actual_listener_status) + { + switch (desired_listener_status) + { + case listener_listening: + react.add(listen, *guard); + actual_listener_status = listener_listening; + break; + case listener_not_listening: + react.remove(listen); + actual_listener_status = listener_not_listening; + break; + } + } + if (!react.size()) + break; + react.do_io(); react.prune(); - if (react.size() == 1 /* 1 listener + 0 sessions */) + int num_sessions; + if (actual_listener_status == listener_listening) + num_sessions = react.size() - 1; + else + num_sessions = react.size(); + if (num_sessions == 0) { // Let the guard die completely if everything's gone quiet. guard->commit(); ============================================================ --- network/reactor.cc fa961bc15a1d0a1a6df66d04b2a57ca63941af34 +++ network/reactor.cc a90cee5442d3c77d8082d7bb91d4d23170bf25fb @@ -88,6 +88,8 @@ void reactor::remove(shared_ptrremove_from_probe(probe); } } ============================================================ --- tests/common/netsync.lua f15a83e9fa031b64b790543973c10f78fcedfe57 +++ tests/common/netsync.lua fc5f1471dd9610885b0e681f41eab2c349ff482a @@ -102,7 +102,16 @@ function netsync.start(opts, n, min) end local mt_wait = mt.wait mt.check = function(obj) return not mt_wait(obj, 0) end - mt.wait = nil -- using this would hang; don't allow it + mt.wait = function(obj, timeout) + if timeout == nil then + timeout = 5 + L(locheader(), "You really should give an argument to server.wait()\n") + end + if type(timeout) ~= "number" then + err("Bad timeout of type "..type(timeout)) + end + return mt_wait(obj, timeout) + end -- wait for "beginning service..." while fsize(out.prefix .. "stderr") == 0 do sleep(1)