Module: Uma::ServerControl
Constant Summary collapse
- BIND_SPEC_RE =
/^(.+)\:(\d+)$/.freeze
Instance Method Summary collapse
- #await_process_termination(machine) ⇒ Object
- #bind_entries(bind_value) ⇒ Object
- #parse_bind_spec(spec) ⇒ Object
- #prepare_listening_socket(machine, host, port) ⇒ Object
- #server_config(env) ⇒ Object
-
#start_acceptors(machine, config, connection_fibers) ⇒ Set<Fiber>
A set of accept fibers.
- #start_connection(machine, config, connection_fibers, fd) ⇒ Fiber
- #start_worker_thread(config, stop_queue) ⇒ Object
- #worker_thread(machine, config, stop_queue) ⇒ Object
- #worker_thread_graceful_stop(machine, accept_fibers, connection_fibers) ⇒ Object
Instance Method Details
#await_process_termination(machine) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/uma/server.rb', line 143 def await_process_termination(machine) sig_queue = UM::Queue.new old_term_handler = trap('SIGTERM') { machine.push(sig_queue, :term) trap('SIGTERM', old_term_handler) } old_int_handler = trap('SIGINT') { machine.push(sig_queue, :int) trap('SIGINT', old_int_handler) } machine.shift(sig_queue) end |
#bind_entries(bind_value) ⇒ Object
47 48 49 50 51 52 53 54 55 56 |
# File 'lib/uma/server.rb', line 47 def bind_entries(bind_value) case bind_value when Array bind_value.map { parse_bind_spec(it) } when String [parse_bind_spec(bind_value)] else raise ArgumentError, "invalid bind value" end end |
#parse_bind_spec(spec) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/uma/server.rb', line 60 def parse_bind_spec(spec) if (m = spec.match(BIND_SPEC_RE)) [m[1], m[2].to_i] else raise ArgumentError, "Invalid bind spec" end end |
#prepare_listening_socket(machine, host, port) ⇒ Object
107 108 109 110 111 112 113 |
# File 'lib/uma/server.rb', line 107 def prepare_listening_socket(machine, host, port) fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0) machine.setsockopt(fd, UM::SOL_SOCKET, UM::SO_REUSEPORT, true) machine.bind(fd, host, port) machine.listen(fd, UM::SOMAXCONN) fd end |
#server_config(env) ⇒ Object
38 39 40 41 42 43 44 45 |
# File 'lib/uma/server.rb', line 38 def server_config(env) { thread_count: 2, bind_entries: env[:bind] ? bind_entries(env[:bind]) : [], connection_proc: env[:connection_proc], error_stream: env[:error_stream] } end |
#start_acceptors(machine, config, connection_fibers) ⇒ Set<Fiber>
Returns a set of accept fibers.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/uma/server.rb', line 88 def start_acceptors(machine, config, connection_fibers) set = Set.new return set if !config[:bind_entries] || config[:bind_entries].empty? config[:bind_entries].each do host, port = it set << machine.spin do fd = prepare_listening_socket(machine, host, port) machine.accept_each(fd) { |fd| start_connection(machine, config, connection_fibers, fd) } rescue UM::Terminate ensure machine.close(fd) end end set end |
#start_connection(machine, config, connection_fibers, fd) ⇒ Fiber
116 117 118 119 120 121 122 123 124 |
# File 'lib/uma/server.rb', line 116 def start_connection(machine, config, connection_fibers, fd) f = machine.spin do connection_fibers << f config[:connection_proc]&.(machine, fd) ensure machine.close(fd) rescue nil connection_fibers.delete(f) end end |
#start_worker_thread(config, stop_queue) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/uma/server.rb', line 68 def start_worker_thread(config, stop_queue) Thread.new do machine = UM.new scheduler = UM::FiberScheduler.new(machine) Fiber.set_scheduler(scheduler) worker_thread(machine, config, stop_queue) end end |
#worker_thread(machine, config, stop_queue) ⇒ Object
78 79 80 81 82 83 84 85 |
# File 'lib/uma/server.rb', line 78 def worker_thread(machine, config, stop_queue) connection_fibers = Set.new accept_fibers = start_acceptors(machine, config, connection_fibers) machine.shift(stop_queue) worker_thread_graceful_stop(machine, accept_fibers, connection_fibers) end |
#worker_thread_graceful_stop(machine, accept_fibers, connection_fibers) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/uma/server.rb', line 126 def worker_thread_graceful_stop(machine, accept_fibers, connection_fibers) # stop accepting connections machine.terminate(accept_fibers) machine.await_fibers(accept_fibers) machine.terminate(connection_fibers) # graceful stop with a timeout of 10 seconds machine.timeout(10, UM::Terminate) do machine.await_fibers(connection_fibers) rescue UM::Terminate alive = connection_fibers.reject(&:done?) machine.terminate(alive) machine.await_fibers(alive) end end |