Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"/rel/<projectname>/bin/<projectname> stop" does not work #46

Closed
farao opened this issue Aug 16, 2016 · 6 comments
Closed

"/rel/<projectname>/bin/<projectname> stop" does not work #46

farao opened this issue Aug 16, 2016 · 6 comments

Comments

@farao
Copy link

farao commented Aug 16, 2016

Same problem like in exrm: bitwalker/exrm#385
It works neither on my laptop (current arch linux) nor on my server (Debian wheezy).

@bitwalker
Copy link
Owner

Can you provide a sample project I can reproduce this with? My own tests have not produced the same issue. I haven't yet tried with an Arch or Debian VM, but I want to make sure this is truly a platform-specific issue and not something more general.

@farao
Copy link
Author

farao commented Aug 17, 2016

You can try this Dockerfile:
Dockerfile.zip

  1. Download into new directory & unzip
  2. sudo docker build ./
  3. sudo docker run -t -i idofdockercontainerfromlastlineoftheoutputofcommand2
  4. (inside docker container) cd signaltower
  5. rel/signal_tower/bin/signal_tower start
  6. rel/signal_tower/bin/signal_tower stop

=> command 6 does not terminate

@farao
Copy link
Author

farao commented Aug 17, 2016

Ok, better try this Dockerfile, I added mix release.init:
Dockerfile.zip

Also I now updated the signaltower repository to use distillery instead of exrm, but the error concerns both as written.

@bitwalker
Copy link
Owner

So the issue here is actually with the app. The problem I found was that when the application master attempts to shut down the signal_tower app, it hangs, and I'm almost certain it's due to the fact that you weren't returning the pid of a supervisor, but of the cowboy HTTP listener. Here's the changes I applied to the signaltower repo to get things working:

diff --git a/lib/signal_tower.ex b/lib/signal_tower.ex
index 80c71ee..daa8e57 100644
--- a/lib/signal_tower.ex
+++ b/lib/signal_tower.ex
@@ -1,28 +1,19 @@
 defmodule SignalTower do
-  @behaviour :application
+  use Application

   def start(_type, _args) do
     import Supervisor.Spec, warn: false

-    start_supervisor()
-    start_cowboy()
-  end
-
-  def stop(_state) do
-    :ok
-  end
-
-  defp start_cowboy() do
     {port, _} = Integer.parse(System.get_env("PALAVA_RTC_ADDRESS") || "4233")

     dispatch = :cowboy_router.compile([
       {:_, [{"/[...]", SignalTower.WebsocketHandler, []}]} # TODO check [] if removable
     ])

-    {:ok, _} = :cowboy.start_http(:http, 100, [{:port, port}], [{:env, [{:dispatch, dispatch}]}])
-  end
-
-  defp start_supervisor() do
-    SignalTower.Supervisor.start_link(%{})
+    children = [
+      supervisor(SignalTower.Supervisor, []),
+      worker(:cowboy, [:http, 100, [port: port], [env: [dispatch: dispatch]]], function: :start_http)
+    ]
+    Supervisor.start_link(children, strategy: :one_for_one)
   end
 end
diff --git a/lib/supervisor.ex b/lib/supervisor.ex
index f55f07b..47f8a94 100644
--- a/lib/supervisor.ex
+++ b/lib/supervisor.ex
@@ -1,8 +1,8 @@
 defmodule SignalTower.Supervisor do
   use Supervisor

-  def start_link(opts) do
-    Supervisor.start_link(__MODULE__, opts)
+  def start_link() do
...skipping...
@@ -1,28 +1,19 @@
 defmodule SignalTower do
-  @behaviour :application
+  use Application

   def start(_type, _args) do
     import Supervisor.Spec, warn: false

-    start_supervisor()
-    start_cowboy()
-  end
-
-  def stop(_state) do
-    :ok
-  end
-
-  defp start_cowboy() do
     {port, _} = Integer.parse(System.get_env("PALAVA_RTC_ADDRESS") || "4233")

     dispatch = :cowboy_router.compile([
       {:_, [{"/[...]", SignalTower.WebsocketHandler, []}]} # TODO check [] if removable
     ])

-    {:ok, _} = :cowboy.start_http(:http, 100, [{:port, port}], [{:env, [{:dispatch, dispatch}]}])
-  end
-
-  defp start_supervisor() do
-    SignalTower.Supervisor.start_link(%{})
+    children = [
+      supervisor(SignalTower.Supervisor, []),
+      worker(:cowboy, [:http, 100, [port: port], [env: [dispatch: dispatch]]], function: :start_http)
+    ]
+    Supervisor.start_link(children, strategy: :one_for_one)
   end
 end
diff --git a/lib/supervisor.ex b/lib/supervisor.ex
index f55f07b..47f8a94 100644
--- a/lib/supervisor.ex
+++ b/lib/supervisor.ex
@@ -1,8 +1,8 @@
 defmodule SignalTower.Supervisor do
   use Supervisor

-  def start_link(opts) do
-    Supervisor.start_link(__MODULE__, opts)
+  def start_link() do
+    Supervisor.start_link(__MODULE__, [])
   end

   def init(_) do

And I used this Dockerfile to test:

FROM debian:wheezy

ENV MIX_ENV=prod

RUN apt-get update && \
    apt-get -y install wget

WORKDIR /opt/code

RUN \
  wget --no-check https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && dpkg -i erlang-solutions_1.0_all.deb &&\
  apt-get update && \
  apt-get -y install elixir && \
  apt-get -y install git && \
  mix local.hex --force && \
  mix local.rebar --force

ADD mix.exs mix.lock ./
RUN mix do deps.get, deps.compile

ADD . .
RUN mix release --verbose --env=prod && \
    mkdir -p /opt/app && \
    cd /opt/app && \
    ls -la /opt/code/rel/signal_tower/releases/1.0.0 && \
    cp /opt/code/rel/signal_tower/releases/1.0.0/signal_tower.tar.gz ./ && \
    tar -xzf signal_tower.tar.gz && \
    mkdir -p ./log && \
    chown -R 777 /opt/app && \
    rm -rf /opt/code

WORKDIR /opt/app

I'm going to close this since it's not an issue with distillery (or exrm)

@farao
Copy link
Author

farao commented Aug 18, 2016

Oh, hmmmm. Strange though that there was no part (elixir compiler, mix or distillery) that warned about this - shouldn't there be a message if the programmer forgets to return the pid of the root supervisor?

Sorry for stealing your time though and thanks a lot for pointing out the problem and solving it at the same time!

@bitwalker
Copy link
Owner

Even dialyzer wouldn't have caught this, because the value you were returning was actually {:ok, pid}, which is what the expected return signature is supposed to be. It's just that the pid was for a process not in your application. Unfortunately I'm not sure that the compiler could ever catch this kind of thing, it's a tricky one for sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants