summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Lemenkov <lemenkov@gmail.com>2020-07-07 14:57:57 +0200
committerGitHub <noreply@github.com>2020-07-07 14:57:57 +0200
commit3dd9db8c62a04c7a81fc9c55c7810d5a81d7b43b (patch)
tree93877d0a21e42f3a128f73f9d26d941475b4235e
parentde603e740a0b2610f9eb05c30f937ee934e4ab67 (diff)
parent0528181ea4ea54e4db21b6ddccf78d7287e57e85 (diff)
downloaderlang-sd_notify-3dd9db8c62a04c7a81fc9c55c7810d5a81d7b43b.tar.gz
Merge pull request #34 from lemenkov/native_unix_socketHEADmaster
Native unix socket
-rw-r--r--README.md10
-rw-r--r--c_src/sd_notify.c75
-rw-r--r--docker/centos_20/Dockerfile2
-rw-r--r--docker/centos_21/Dockerfile2
-rw-r--r--docker/centos_22/Dockerfile2
-rw-r--r--docker/ubuntu_20/Dockerfile4
-rw-r--r--docker/ubuntu_21/Dockerfile4
-rw-r--r--packaging/centos/erlang-sd_notify.spec9
-rw-r--r--packaging/deb/Makefile1
-rw-r--r--packaging/deb/debian/control4
-rw-r--r--packaging/deb/debian/erlang-sd-notify.dirs1
-rw-r--r--rebar.config2
-rw-r--r--src/sd_notify.app.src2
-rw-r--r--src/sd_notify.erl67
-rw-r--r--test/sd_notify_test.erl61
15 files changed, 114 insertions, 132 deletions
diff --git a/README.md b/README.md
index 5d7c937..6ea2bac 100644
--- a/README.md
+++ b/README.md
@@ -10,10 +10,10 @@ Installation
============
On Fedora/CentOS
-
+
```bash
rpm -i erlang-sd_notify-{version}-1.el7.centos.x86_64.rpm
-```
+```
On Debian/Ubuntu
@@ -32,7 +32,7 @@ sudo zypper --gpg-auto-import-keys refresh
sudo zypper install erlang-sd_notify
```
-
+
Build from source using Docker
===
@@ -59,7 +59,7 @@ Example
Download Binaries
===
-[Github Repository](https://github.com/systemd/erlang-sd_notify/releases)
+[Github Repository](https://github.com/systemd/erlang-sd_notify/releases)
Usage
=====
@@ -68,7 +68,7 @@ Quick example:
```bash
[root@a499ee66251a]# erl
- ...
+ ...
1> sd_notify:sd_notify(0,"READY=1").
0
```
diff --git a/c_src/sd_notify.c b/c_src/sd_notify.c
deleted file mode 100644
index 5c21be4..0000000
--- a/c_src/sd_notify.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-This is the MIT license.
-
-Copyright (c) 2014 Peter Lemenkov <lemenkov@gmail.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this
-software and associated documentation files (the "Software"), to deal in the Software
-without restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be included in all copies
-or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "erl_nif.h"
-#include <systemd/sd-daemon.h>
-
-static int upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
-{
- return 0;
-}
-
-static ERL_NIF_TERM sd_pid_notify_with_fds_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{
- ERL_NIF_TERM head, tail;
- unsigned int length = 0;
-
- pid_t pid = 0;
- enif_get_int(env, argv[0], &pid);
-
- int unset_environment = 0;
- enif_get_int(env, argv[1], &unset_environment);
-
- enif_get_list_length(env, argv[2], &length);
- char* state = (char*)enif_alloc(++length);
- enif_get_string(env, argv[2], state, length, ERL_NIF_LATIN1);
-
- enif_get_list_length(env, argv[3], &length);
- int* fds = (int*)enif_alloc(length * sizeof(int));
- ERL_NIF_TERM list = argv[3];
- int i = 0;
- while(enif_get_list_cell(env, list, &head, &tail)) {
- enif_get_int(env, head, &fds[i]);
- i++;
- list = tail;
- }
- int result = sd_pid_notify_with_fds(pid, unset_environment, state, fds, length);
-
- enif_free(fds);
- enif_free(state);
-
- return enif_make_int(env, result);
-}
-
-static ErlNifFunc nif_funcs[] =
-{
- {"sd_pid_notify_with_fds", 4, sd_pid_notify_with_fds_nif},
-
-};
-
-// Initialize this NIF library.
-//
-// Args: (MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)
-// Docs: http://erlang.org/doc/man/erl_nif.html#ERL_NIF_INIT
-
-ERL_NIF_INIT(sd_notify, nif_funcs, NULL, NULL, &upgrade, NULL);
diff --git a/docker/centos_20/Dockerfile b/docker/centos_20/Dockerfile
index e9b2294..04513fc 100644
--- a/docker/centos_20/Dockerfile
+++ b/docker/centos_20/Dockerfile
@@ -3,8 +3,6 @@ FROM centos
RUN yum -y update
RUN yum install -y \
- gcc \
- systemd-devel \
make \
git \
wget \
diff --git a/docker/centos_21/Dockerfile b/docker/centos_21/Dockerfile
index 6511c0d..27aac68 100644
--- a/docker/centos_21/Dockerfile
+++ b/docker/centos_21/Dockerfile
@@ -3,8 +3,6 @@ FROM centos
RUN yum -y update
RUN yum install -y \
- gcc \
- systemd-devel \
make \
git \
wget \
diff --git a/docker/centos_22/Dockerfile b/docker/centos_22/Dockerfile
index 2e9ef67..eb93684 100644
--- a/docker/centos_22/Dockerfile
+++ b/docker/centos_22/Dockerfile
@@ -3,8 +3,6 @@ FROM centos
RUN yum -y update
RUN yum install -y \
- gcc \
- systemd-devel \
make \
git \
wget \
diff --git a/docker/ubuntu_20/Dockerfile b/docker/ubuntu_20/Dockerfile
index 6adcdf3..766c3f9 100644
--- a/docker/ubuntu_20/Dockerfile
+++ b/docker/ubuntu_20/Dockerfile
@@ -3,15 +3,13 @@ FROM ubuntu:16.04
RUN apt-get -y update
RUN apt-get install -y \
- gcc \
make \
git \
wget \
build-essential \
devscripts \
fakeroot \
- debhelper \
- libsystemd-dev
+ debhelper
RUN wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
diff --git a/docker/ubuntu_21/Dockerfile b/docker/ubuntu_21/Dockerfile
index eecdb52..666cb73 100644
--- a/docker/ubuntu_21/Dockerfile
+++ b/docker/ubuntu_21/Dockerfile
@@ -3,15 +3,13 @@ FROM ubuntu:16.04
RUN apt-get -y update
RUN apt-get install -y \
- gcc \
make \
git \
wget \
build-essential \
devscripts \
fakeroot \
- debhelper \
- libsystemd-dev
+ debhelper
RUN wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
diff --git a/packaging/centos/erlang-sd_notify.spec b/packaging/centos/erlang-sd_notify.spec
index ea2cd26..6a3509c 100644
--- a/packaging/centos/erlang-sd_notify.spec
+++ b/packaging/centos/erlang-sd_notify.spec
@@ -14,14 +14,12 @@ VCS: scm:git:https://github.com/%{upstream}/%{realname}.git
Source0: https://github.com/%{upstream}/%{realname}/archive/%{version}/erlang-%{realname}-%{version}.tar.gz
Source1: erlang-sd_notify-rebar.config
BuildRequires: erlang-rebar
-BuildRequires: systemd-devel
-%{?__erlang_nif_version:Requires: %{__erlang_nif_version}}
%description
%{summary}.
-%prep
+%prep
%setup -c .
%build
@@ -29,20 +27,17 @@ rebar compile
%install
-mkdir -p $RPM_BUILD_ROOT%{_libdir}/erlang/lib/%{realname}-%{version}/{ebin,priv}
+mkdir -p $RPM_BUILD_ROOT%{_libdir}/erlang/lib/%{realname}-%{version}/ebin
install -m 644 -p ebin/%{realname}.app $RPM_BUILD_ROOT%{_libdir}/erlang/lib/%{realname}-%{version}/ebin
install -m 644 -p ebin/%{realname}.beam $RPM_BUILD_ROOT%{_libdir}/erlang/lib/%{realname}-%{version}/ebin
-install -m 755 -p priv/%{realname}_drv.so $RPM_BUILD_ROOT%{_libdir}/erlang/lib/%{realname}-%{version}/priv
%files
%doc LICENSE
%dir %{_libdir}/erlang/lib/%{realname}-%{version}/
%dir %{_libdir}/erlang/lib/%{realname}-%{version}/ebin/
-%dir %{_libdir}/erlang/lib/%{realname}-%{version}/priv/
%{_libdir}/erlang/lib/%{realname}-%{version}/ebin/%{realname}.app
%{_libdir}/erlang/lib/%{realname}-%{version}/ebin/%{realname}.beam
-%{_libdir}/erlang/lib/%{realname}-%{version}/priv/%{realname}_drv.so
%changelog
diff --git a/packaging/deb/Makefile b/packaging/deb/Makefile
index dd8bf0a..5272597 100644
--- a/packaging/deb/Makefile
+++ b/packaging/deb/Makefile
@@ -30,4 +30,3 @@ deb-install:
pwd
install -o root -g root -t $(TARGET_DIR)/ebin ../../ebin/*.app
install -o root -g root -t $(TARGET_DIR)/ebin ../../ebin/*.beam
- install -o root -g root -t $(TARGET_DIR)/priv ../../priv/*.so
diff --git a/packaging/deb/debian/control b/packaging/deb/debian/control
index ff30267..d9fea23 100644
--- a/packaging/deb/debian/control
+++ b/packaging/deb/debian/control
@@ -5,12 +5,10 @@ Priority: optional
Standards-Version: 3.9.2
Build-Depends: debhelper (>= 9),
erlang-dev (>=17.3-dfsg-4),
- libsystemd-dev (>=215),
rebar,
Package: erlang-sd-notify
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends},
- erlang-base (>=17.3) | erlang-base-hipe (>=17.3),
- libsystemd0 (>=215),
+ erlang-base (>=17.3) | erlang-base-hipe (>=17.3)
Description: Systemd notification support for Erlang.
diff --git a/packaging/deb/debian/erlang-sd-notify.dirs b/packaging/deb/debian/erlang-sd-notify.dirs
index 1b9362c..0f90a75 100644
--- a/packaging/deb/debian/erlang-sd-notify.dirs
+++ b/packaging/deb/debian/erlang-sd-notify.dirs
@@ -1,2 +1 @@
usr/lib/erlang/lib/sd_notify-%VERSION%/ebin
-usr/lib/erlang/lib/sd_notify-%VERSION%/priv
diff --git a/rebar.config b/rebar.config
index 4f871b1..422726d 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,3 +1 @@
-{port_env, [{"LDFLAGS", "$LDFLAGS -lsystemd"}]}.
-
{erl_opts, [debug_info, warnings_as_errors]}.
diff --git a/src/sd_notify.app.src b/src/sd_notify.app.src
index da3ae2f..f936bd2 100644
--- a/src/sd_notify.app.src
+++ b/src/sd_notify.app.src
@@ -1,6 +1,6 @@
{application, sd_notify,
[
- {description, "Erlang sd_notify NIF"},
+ {description, "Erlang sd_notify API"},
{vsn, "git"},
{registered, []},
{applications, [
diff --git a/src/sd_notify.erl b/src/sd_notify.erl
index c5201da..c0bb824 100644
--- a/src/sd_notify.erl
+++ b/src/sd_notify.erl
@@ -29,23 +29,43 @@
-export([sd_notify/2, sd_notifyf/3, sd_pid_notify/3, sd_pid_notifyf/4, sd_pid_notify_with_fds/4]).
--on_load(init/0).
+-export([ready/0, reloading/0, stopping/0, watchdog/0]).
+-export([start_link/0]).
+-export([init/1, handle_info/2, terminate/2]).
--define(nif_stub, nif_stub_error(?LINE)).
+% API helpers
-nif_stub_error(Line) ->
- erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
+ready() -> sd_pid_notify_with_fds(0, false, <<"READY=1">>, []).
+reloading() -> sd_pid_notify_with_fds(0, false, <<"RELOADING=1">>, []).
+stopping() -> sd_pid_notify_with_fds(0, false, <<"STOPPING=1">>, []).
+watchdog() -> sd_pid_notify_with_fds(0, false, <<"WATCHDOG=1">>, []).
-init() ->
- PrivDir = case code:priv_dir(?MODULE) of
- {error, bad_name} ->
- EbinDir = filename:dirname(code:which(?MODULE)),
- AppPath = filename:dirname(EbinDir),
- filename:join(AppPath, "priv");
- Path ->
- Path
- end,
- erlang:load_nif(filename:join(PrivDir, ?MODULE) ++ "_drv", 0).
+% gen_server API and callbacks
+
+start_link() ->
+ gen_server:start_link({local,?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ WatchdogMs = case os:getenv( "WATCHDOG_USEC" ) of
+ false -> none;
+ Value ->
+ Part = erlang:round(0.8 * erlang:list_to_integer(Value)),
+ erlang:convert_time_unit(Part, microsecond, millisecond)
+ end,
+ erlang:send_after(WatchdogMs, self(), watchdog),
+ error_logger:info_msg("watchdog: ~p ms", [WatchdogMs]),
+ {ok, WatchdogMs}.
+
+handle_info(watchdog, none) ->
+ {noreply, none};
+handle_info(watchdog, WatchdogMs) ->
+ watchdog(),
+ erlang:send_after(WatchdogMs, self(), watchdog),
+ {noreply, WatchdogMs}.
+
+terminate(_,_) -> ok.
+
+% Systemd API
sd_notify(UnsetEnv, Data) ->
sd_pid_notify_with_fds(0, UnsetEnv, Data, []).
@@ -59,5 +79,20 @@ sd_notifyf(UnsetEnv, Format, Data) ->
sd_pid_notifyf(Pid, UnsetEnv, Format, Data) ->
sd_pid_notify_with_fds(Pid, UnsetEnv, lists:flatten(io_lib:format(Format, Data)), []).
-sd_pid_notify_with_fds(_, _, _, _) ->
- ?nif_stub.
+sd_pid_notify_with_fds(_Pid, UnsetEnv, Call, _Fds) ->
+ error_logger:info_msg("systemd: ~p", [Call]),
+ case os:getenv("NOTIFY_SOCKET") of
+ false -> {error, not_configured};
+ Path ->
+ case gen_udp:open(0, [local]) of
+ {error, SocketError} ->
+ {error, SocketError};
+ {ok, Socket} ->
+ Result = gen_udp:send(Socket, {local,Path}, 0, Call),
+ gen_udp:close(Socket),
+
+ UnsetEnv == true andalso os:unsetenv("NOTIFY_SOCKET"),
+
+ Result
+ end
+ end.
diff --git a/test/sd_notify_test.erl b/test/sd_notify_test.erl
index 4ae437a..59df682 100644
--- a/test/sd_notify_test.erl
+++ b/test/sd_notify_test.erl
@@ -2,11 +2,7 @@
-include_lib("eunit/include/eunit.hrl").
-
-sd_notify_test_() ->
- sd_notify_test_local(erlang:system_info(otp_release)).
-
-sd_notify_test_local("19") ->
+sd_notify_basic_test_() ->
{ok, CWD} = file:get_cwd(),
FakeNotifyUnixSockName = CWD ++ "/fake-sock-" ++ integer_to_list(erlang:phash2(make_ref())),
{ok, FakeNotifyUnixSock} = gen_udp:open(0, [{ifaddr, {local, FakeNotifyUnixSockName}}, {active, false}, list]),
@@ -20,7 +16,7 @@ sd_notify_test_local("19") ->
"Try sending message",
fun() ->
TestMessage = integer_to_list(erlang:phash2(make_ref())),
- 1 = sd_notify:sd_pid_notify_with_fds(0, 0, TestMessage, []),
+ ok = sd_notify:sd_pid_notify_with_fds(0, 0, TestMessage, []),
{ok, {_Address, _Port, Packet}} = gen_udp:recv(FakeNotifyUnixSock, length(TestMessage), 1000),
?assertEqual(TestMessage, Packet)
end
@@ -28,6 +24,53 @@ sd_notify_test_local("19") ->
]
- };
-sd_notify_test_local(_) ->
- [].
+ }.
+
+sd_notify_unsetenv_test_() ->
+ {ok, CWD} = file:get_cwd(),
+ FakeNotifyUnixSockName = CWD ++ "/fake-sock-" ++ integer_to_list(erlang:phash2(make_ref())),
+ {ok, FakeNotifyUnixSock} = gen_udp:open(0, [{ifaddr, {local, FakeNotifyUnixSockName}}, {active, false}, list]),
+ os:putenv("NOTIFY_SOCKET", FakeNotifyUnixSockName),
+
+ {setup,
+ fun() -> ok end,
+ fun(_) -> ok = gen_udp:close(FakeNotifyUnixSock), ok = file:delete(FakeNotifyUnixSockName) end,
+ [
+ {
+ "Try sending message",
+ fun() ->
+ TestMessage = integer_to_list(erlang:phash2(make_ref())),
+ ok = sd_notify:sd_pid_notify_with_fds(0, true, TestMessage, []),
+ {ok, {_Address, _Port, _Packet}} = gen_udp:recv(FakeNotifyUnixSock, length(TestMessage), 1000),
+ Ret = os:getenv("NOTIFY_SOCKET"),
+ ?assertEqual(Ret, false)
+ end
+ }
+
+ ]
+
+ }.
+
+sd_notify_watchdog_test_() ->
+ {ok, CWD} = file:get_cwd(),
+ FakeNotifyUnixSockName = CWD ++ "/fake-sock-" ++ integer_to_list(erlang:phash2(make_ref())),
+ {ok, FakeNotifyUnixSock} = gen_udp:open(0, [{ifaddr, {local, FakeNotifyUnixSockName}}, {active, false}, list]),
+ os:putenv("NOTIFY_SOCKET", FakeNotifyUnixSockName),
+
+ {setup,
+ fun() -> ok end,
+ fun(_) -> ok = gen_udp:close(FakeNotifyUnixSock), ok = file:delete(FakeNotifyUnixSockName) end,
+ [
+ {
+ "Try sending message",
+ fun() ->
+ os:putenv("WATCHDOG_USEC", "500000"),
+ sd_notify:start_link(),
+ {ok, {_Address, _Port, Packet}} = gen_udp:recv(FakeNotifyUnixSock, length("WATCHDOG=1"), 1000),
+ ?assertEqual("WATCHDOG=1", Packet)
+ end
+ }
+
+ ]
+
+ }.