Skip to content

Commit f8fcd67

Browse files
committed
ft: add support for notify-reload and automatic reload handling
1 parent 62723b2 commit f8fcd67

File tree

18 files changed

+310
-207
lines changed

18 files changed

+310
-207
lines changed

examples/echo/config/sys.config

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[
2-
{echo, []}
2+
{echo, []},
3+
{kernel, [{logger_level, debug}]}
34
].

examples/echo/src/echo_app.erl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
start(_StartType, _StartArgs) ->
1515
case logger:add_handlers(systemd) of
1616
ok ->
17-
case systemd:is_journal(standard_io) of
18-
true -> logger:remove_handler(default);
19-
_ -> ok
20-
end;
17+
logger:remove_handler(default);
2118
_ ->
2219
ok
2320
end,

examples/echo/systemd/echo.service

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
[Unit]
22
Description=Echo service in Erlang
3-
Requires=epmd.socket
3+
; Requires=epmd.socket
44
After=echo-tcp.socket echo-udp.socket
55
BindsTo=echo-tcp.socket echo-udp.socket
66

77
[Service]
88
# Create required directories configure HOME
99
Environment=HOME=/run/%N
1010
RuntimeDirectory=%N
11+
LogsDirectory=%N
1112

1213
# Do not start EPMD as this is managed by `epmd.socket`
1314
Environment='ERL_FLAGS=-start_epmd false'
15+
Environment=ERL_CRASH_DUMP=/var/log/%N/erl_crash.dump
1416

1517
DynamicUser=true
16-
Type=notify
18+
Type=notify-reload
1719
ExecStart=/opt/echo/bin/echo foreground
1820
WatchdogSec=1min
1921
NotifyAccess=main

examples/plug/lib/plug_systemd_example/application.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ defmodule PlugSystemdExample.Application do
4343

4444
"bandit" ->
4545
[
46-
{Bandit, basic_opts ++ [options: [port: port, transport_options: transport_opts]]}
46+
{Bandit,
47+
basic_opts ++
48+
[thousand_island_options: [port: port, transport_options: transport_opts]]}
4749
]
4850
end
4951

@@ -79,8 +81,7 @@ defmodule PlugSystemdExample.Application do
7981

8082
{0,
8183
[
82-
port: 0,
83-
net: :inet6,
84+
:inet6,
8485
fd: fd
8586
]}
8687
end

examples/plug/lib/plug_systemd_example/router.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ defmodule PlugSystemdExample.Router do
6262
get "/slow" do
6363
conn = send_chunked(conn, 200)
6464

65-
Enum.reduce_while('I am so sloooooow', conn, fn chunk, conn ->
65+
Enum.reduce_while(~c'I am so sloooooow', conn, fn chunk, conn ->
6666
case chunk(conn, [chunk, "\n"]) do
6767
{:ok, conn} ->
6868
Process.sleep(500)

examples/plug/mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ defmodule PlugSystemdExample.MixProject do
3030
[
3131
{:plug, "~> 1.0"},
3232
{:plug_cowboy, "~> 2.0"},
33-
{:dialyxir, ">= 0.0.0"},
33+
{:dialyxir, ">= 0.0.0", only: :dev, runtime: false},
3434
{:bandit, ">= 0.0.0"},
3535
{:systemd, path: "../.."}
3636
]

examples/plug/mix.lock

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
%{
2-
"bandit": {:hex, :bandit, "0.7.7", "48456d09022607a312cf723a91992236aeaffe4af50615e6e2d2e383fb6bef10", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 0.6.7", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "772f0a32632c2ce41026d85e24b13a469151bb8cea1891e597fb38fde103640a"},
3-
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
2+
"bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"},
3+
"cowboy": {:hex, :cowboy, "2.13.0", "09d770dd5f6a22cc60c071f432cd7cb87776164527f205c5a6b0f24ff6b38990", [:make, :rebar3], [{:cowlib, ">= 2.14.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e724d3a70995025d654c1992c7b11dbfea95205c047d86ff9bf1cda92ddc5614"},
44
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
5-
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
6-
"dialyxir": {:hex, :dialyxir, "1.3.0", "fd1672f0922b7648ff9ce7b1b26fcf0ef56dda964a459892ad15f6b4410b5284", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "00b2a4bcd6aa8db9dcb0b38c1225b7277dca9bc370b6438715667071a304696f"},
5+
"cowlib": {:hex, :cowlib, "2.15.0", "3c97a318a933962d1c12b96ab7c1d728267d2c523c25a5b57b0f93392b6e9e25", [:make, :rebar3], [], "hexpm", "4f00c879a64b4fe7c8fcb42a4281925e9ffdb928820b03c3ad325a617e857532"},
6+
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
77
"enough": {:hex, :enough, "0.1.0", "0254710c52d324e2dadde54cb56fbb80a792c2eb285669b8379efd0752bf89f0", [:rebar3], [], "hexpm", "0460c7abda5f5e0ea592b12bc6976b8a5c4b96e42f332059cd396525374bf9a1"},
8-
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
9-
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
10-
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
11-
"plug": {:hex, :plug, "1.14.2", "cff7d4ec45b4ae176a227acd94a7ab536d9b37b942c8e8fa6dfc0fff98ff4d80", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "842fc50187e13cf4ac3b253d47d9474ed6c296a8732752835ce4a86acdf68d13"},
12-
"plug_cowboy": {:hex, :plug_cowboy, "2.6.1", "9a3bbfceeb65eff5f39dab529e5cd79137ac36e913c02067dba3963a26efe9b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613"},
13-
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
14-
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
15-
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
16-
"thousand_island": {:hex, :thousand_island, "0.6.7", "3a91a7e362ca407036c6691e8a4f6e01ac8e901db3598875863a149279ac8571", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "541a5cb26b88adf8d8180b6b96a90f09566b4aad7a6b3608dcac969648cf6765"},
17-
"websock": {:hex, :websock, "0.5.2", "b3c08511d8d79ed2c2f589ff430bd1fe799bb389686dafce86d28801783d8351", [:mix], [], "hexpm", "925f5de22fca6813dfa980fb62fd542ec43a2d1a1f83d2caec907483fe66ff05"},
8+
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
9+
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
10+
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
11+
"plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
12+
"plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"},
13+
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
14+
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
15+
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
16+
"thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"},
17+
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
1818
}

examples/plug/systemd/plug.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ RuntimeDirectory=%N
1414
# -kernel inet_backend socket'
1515

1616
DynamicUser=true
17-
Type=notify
17+
Type=notify-reload
1818
ExecStart=/opt/plug/bin/plug start
1919
WatchdogSec=1min
2020
NotifyAccess=main

src/systemd.app.src

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
]},
1414
{mod, {systemd_app, []}},
1515
{env, [
16-
{unset_env, true},
1716
{install_kmsg, true},
18-
{watchdog_scale, 2},
17+
{handle_event, sighup},
18+
{watchdog_scale, 10},
1919
{warn_about_readiness_message, 10000},
2020
{logger, [
2121
{handler, systemd_journal, systemd_journal_h, #{

src/systemd.erl

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
-include("systemd_internal.hrl").
4848

4949
-export([
50-
unset_env/1,
5150
notify/1,
5251
ready/0,
5352
ready/1,
@@ -65,47 +64,6 @@
6564

6665
-export([notify_spawn/2]).
6766

68-
%% @doc
69-
%% Unset environment variables for given subsystem.
70-
%%
71-
%% Most environment variables will be cleaned on startup by default. To prevent
72-
%% such behaviour set `unset_env' application variable to `false'.
73-
%%
74-
%% <dl>
75-
%% <dt>`unset_env(notify)'</dt>
76-
%% <dd>Unset variables used by {@link notify/1. `notify/1'}. This call will
77-
%% be done automatically when the `unset_env' application option is set
78-
%% (default). It is highly encouraged to unset these variables to prevent
79-
%% them from being passed to subprocesses.</dd>
80-
%% <dt>`unset_env(watchdog)'</dt>
81-
%% <dd>Unset variables used by {@link watchdog/1. `watchdog/1'}. This call
82-
%% will be done automatically when the `unset_env' application option is
83-
%% set (default). It is highly encouraged to unset these variables
84-
%% to prevent them from being passed to subprocesses.</dd>
85-
%% <dt>`unset_env(listen_fds)'</dt>
86-
%% <dd>Unset variables used by {@link listen_fds/0. `listen_fds/0'}. After
87-
%% that all subsequent calls to `listen_fds' will return empty list. It is
88-
%% highly encouraged to unset these variables to prevent them from being
89-
%% passed to the subprocesses.</dd>
90-
%% </dl>
91-
%%
92-
%% @since 0.4.0
93-
%% @end
94-
-spec unset_env(Subsystem) -> ok when
95-
Subsystem :: notify | watchdog | listen_fds.
96-
unset_env(notify) ->
97-
os:unsetenv(?NOTIFY_SOCKET),
98-
ok;
99-
unset_env(watchdog) ->
100-
os:unsetenv(?WATCHDOG_PID),
101-
os:unsetenv(?WATCHDOG_TIMEOUT),
102-
ok;
103-
unset_env(listen_fds) ->
104-
os:unsetenv(?LISTEN_PID),
105-
os:unsetenv(?LISTEN_FDS),
106-
os:unsetenv(?LISTEN_FDNAMES),
107-
ok.
108-
10967
%% ----------------------------------------------------------------------------
11068

11169
%% @doc
@@ -166,7 +124,9 @@ normalize_state([ready | Rest]) ->
166124
normalize_state([stopping | Rest]) ->
167125
[{stopping, "1"} | normalize_state(Rest)];
168126
normalize_state([reloading | Rest]) ->
169-
Microsecs = erlang:monotonic_time(microsecond),
127+
% erlang:monotonic_time can return negative value so we adjust it to 64 bit
128+
% positive integer
129+
Microsecs = erlang:monotonic_time(microsecond) + 9223372036854775808,
170130
[
171131
{reloading, "1"},
172132
{"MONOTONIC_USEC", integer_to_binary(Microsecs)}
@@ -277,6 +237,7 @@ reload() -> reload([]).
277237
-spec reload(Opts :: [{mode, init:mode()}]) -> ok.
278238
reload(Opts) ->
279239
persistent_term:put({?MODULE, shutdown}, reloading),
240+
systemd_env:reset(),
280241
init:restart(Opts).
281242

282243
%% ----------------------------------------------------------------------------
@@ -312,7 +273,7 @@ reload(Opts) ->
312273
%% <dd>Divider of the timeout to send messages more often than this is
313274
%% required to prevent any jitter.
314275
%%
315-
%% Defaults to `2' which will send messages twice as often as needed.</dd>
276+
%% Defaults to `10' which will send messages 10 times as often as needed.</dd>
316277
%% <dt>`watchdog_check'</dt>
317278
%% <dd>Function (specified as 0-ary function or `mfa()') that will be ran
318279
%% before pinging watchdog process. Such function should return `true' if
@@ -441,10 +402,11 @@ credentials(Name) ->
441402
%% @end
442403
-spec listen_fds() -> [fd()].
443404
listen_fds() ->
444-
case check_listen_pid() of
405+
Env = systemd_env:get(),
406+
case check_listen_pid(Env) of
445407
true ->
446-
Count = listen_fds_count(),
447-
Names = listen_names(),
408+
Count = listen_fds_count(Env),
409+
Names = listen_names(Env),
448410
generate_fds(Count, Names);
449411
false ->
450412
[]
@@ -492,11 +454,11 @@ clear_fds(Names) ->
492454
[]
493455
).
494456

495-
check_listen_pid() ->
496-
os:getenv(?LISTEN_PID) == os:getpid().
457+
check_listen_pid(#{listen_pid := ListenPid}) ->
458+
ListenPid == os:getpid().
497459

498-
listen_fds_count() ->
499-
case os:getenv(?LISTEN_FDS) of
460+
listen_fds_count(#{listen_fds := ListenFds}) ->
461+
case ListenFds of
500462
false ->
501463
0;
502464
Env ->
@@ -506,8 +468,8 @@ listen_fds_count() ->
506468
end
507469
end.
508470

509-
listen_names() ->
510-
case os:getenv(?LISTEN_FDNAMES) of
471+
listen_names(#{listen_fdnames := ListenFDNames}) ->
472+
case ListenFDNames of
511473
false -> [];
512474
Env -> string:split(Env, ":", all)
513475
end.

0 commit comments

Comments
 (0)