shutdown_SUITE.erl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. %% Copyright (c) 2013-2018, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. -module(shutdown_SUITE).
  15. -compile(export_all).
  16. -compile(nowarn_export_all).
  17. -import(ct_helper, [doc/1]).
  18. -import(ct_helper, [name/0]).
  19. %% ct.
  20. all() ->
  21. ct_helper:all(?MODULE).
  22. %% Tests.
  23. brutal_kill(_) ->
  24. doc("Shutdown Ranch listener with shutdown option set to brutal_kill."),
  25. Name = name(),
  26. {ok, ListenerSup} = ranch:start_listener(Name,
  27. ranch_tcp, [{port, 0}, {shutdown, brutal_kill}],
  28. echo_protocol, []),
  29. Port = ranch:get_port(Name),
  30. {ok, _} = gen_tcp:connect("localhost", Port, []),
  31. receive after 100 -> ok end,
  32. ListenerSupChildren = supervisor:which_children(ListenerSup),
  33. {_, ConnsSup, _, _} = lists:keyfind(ranch_conns_sup, 1, ListenerSupChildren),
  34. [{_, Pid, _, _}] = supervisor:which_children(ConnsSup),
  35. true = is_process_alive(Pid),
  36. ok = ranch:stop_listener(Name),
  37. receive after 100 -> ok end,
  38. false = is_process_alive(Pid),
  39. false = is_process_alive(ListenerSup),
  40. {error, _} = gen_tcp:connect("localhost", Port, []),
  41. ok.
  42. infinity(_) ->
  43. doc("Shutdown Ranch listener with shutdown option set to infinity."),
  44. Name = name(),
  45. {ok, ListenerSup} = ranch:start_listener(Name,
  46. ranch_tcp, [{port, 0}, {shutdown, infinity}],
  47. echo_protocol, []),
  48. Port = ranch:get_port(Name),
  49. {ok, _} = gen_tcp:connect("localhost", Port, []),
  50. receive after 100 -> ok end,
  51. ListenerSupChildren = supervisor:which_children(ListenerSup),
  52. {_, ConnsSup, _, _} = lists:keyfind(ranch_conns_sup, 1, ListenerSupChildren),
  53. [{_, Pid, _, _}] = supervisor:which_children(ConnsSup),
  54. true = is_process_alive(Pid),
  55. ok = ranch:stop_listener(Name),
  56. receive after 100 -> ok end,
  57. false = is_process_alive(Pid),
  58. false = is_process_alive(ListenerSup),
  59. {error, _} = gen_tcp:connect("localhost", Port, []),
  60. ok.
  61. infinity_trap_exit(_) ->
  62. doc("Shutdown Ranch listener with shutdown option set to infinity "
  63. "and protocol process trapping exits. The listener must not stop "
  64. "until the protocol process terminates."),
  65. Name = name(),
  66. {ok, ListenerSup} = ranch:start_listener(Name,
  67. ranch_tcp, [{port, 0}, {shutdown, infinity}],
  68. trap_exit_protocol, []),
  69. Port = ranch:get_port(Name),
  70. {ok, _} = gen_tcp:connect("localhost", Port, []),
  71. receive after 100 -> ok end,
  72. ListenerSupChildren = supervisor:which_children(ListenerSup),
  73. {_, ConnsSup, _, _} = lists:keyfind(ranch_conns_sup, 1, ListenerSupChildren),
  74. [{_, Pid, _, _}] = supervisor:which_children(ConnsSup),
  75. true = is_process_alive(Pid),
  76. %% This call will block infinitely.
  77. SpawnPid = spawn(fun() -> ok = ranch:stop_listener(Name) end),
  78. receive after 100 -> ok end,
  79. %% The protocol traps exit signals, and ignore them, so it won't die.
  80. true = is_process_alive(Pid),
  81. %% The listener will stay up forever too.
  82. true = is_process_alive(ListenerSup),
  83. %% We can't connect, though.
  84. {error, _} = gen_tcp:connect("localhost", Port, []),
  85. %% Killing the process unblocks everything.
  86. exit(Pid, kill),
  87. receive after 100 -> ok end,
  88. false = is_process_alive(ListenerSup),
  89. false = is_process_alive(SpawnPid),
  90. ok.
  91. timeout(_) ->
  92. doc("Shutdown Ranch listener with shutdown option set to 500ms."),
  93. Name = name(),
  94. {ok, ListenerSup} = ranch:start_listener(Name,
  95. ranch_tcp, [{port, 0}, {shutdown, 500}],
  96. echo_protocol, []),
  97. Port = ranch:get_port(Name),
  98. {ok, _} = gen_tcp:connect("localhost", Port, []),
  99. receive after 100 -> ok end,
  100. ListenerSupChildren = supervisor:which_children(ListenerSup),
  101. {_, ConnsSup, _, _} = lists:keyfind(ranch_conns_sup, 1, ListenerSupChildren),
  102. [{_, Pid, _, _}] = supervisor:which_children(ConnsSup),
  103. true = is_process_alive(Pid),
  104. ok = ranch:stop_listener(Name),
  105. receive after 100 -> ok end,
  106. false = is_process_alive(Pid),
  107. false = is_process_alive(ListenerSup),
  108. {error, _} = gen_tcp:connect("localhost", Port, []),
  109. ok.
  110. timeout_trap_exit(_) ->
  111. doc("Shutdown Ranch listener with shutdown option set to 500ms "
  112. "and protocol process trapping exits. The listener will only stop "
  113. "after the 500ms timeout."),
  114. Name = name(),
  115. {ok, ListenerSup} = ranch:start_listener(Name,
  116. ranch_tcp, [{port, 0}, {shutdown, 500}],
  117. trap_exit_protocol, []),
  118. Port = ranch:get_port(Name),
  119. {ok, _} = gen_tcp:connect("localhost", Port, []),
  120. receive after 100 -> ok end,
  121. ListenerSupChildren = supervisor:which_children(ListenerSup),
  122. {_, ConnsSup, _, _} = lists:keyfind(ranch_conns_sup, 1, ListenerSupChildren),
  123. [{_, Pid, _, _}] = supervisor:which_children(ConnsSup),
  124. true = is_process_alive(Pid),
  125. %% This call will block for the duration of the shutdown.
  126. SpawnPid = spawn(fun() -> ok = ranch:stop_listener(Name) end),
  127. receive after 100 -> ok end,
  128. %% The protocol traps exit signals, and ignore them, so it won't die.
  129. true = is_process_alive(Pid),
  130. %% The listener will stay up for now too.
  131. true = is_process_alive(ListenerSup),
  132. %% We can't connect, though.
  133. {error, _} = gen_tcp:connect("localhost", Port, []),
  134. %% Wait for the timeout to finish and see that everything is killed.
  135. receive after 500 -> ok end,
  136. false = is_process_alive(Pid),
  137. false = is_process_alive(ListenerSup),
  138. false = is_process_alive(SpawnPid),
  139. ok.