<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;
      charset=windows-1252">
  </head>
  <body>
    <div class="moz-cite-prefix">Most usage of
      application:ensure_all_started/1 wouldn't want it to hang due to
      permissions because that wouldn't be fail-fast and the usage would
      often be for testing that needs to fail (the system state is not
      as expected).<br>
      <br>
      Your desire to have the permissions cause the application start
      sequence to hang would be part of manual interaction with the
      application start sequence.  So, it seems best to have that in a
      separate function that is specifically for manual interaction with
      the applications, like application:await_all_started/1 .<br>
      <br>
      I would want to avoid functionality that can cause the execution
      to hang, so I would avoid permissions and
      application:await_all_started/1 to keep the execution of
      higher-level source code predictable.  One way of resolving these
      separate use-cases is to have any hang-execution functionality in
      a separate module, like application_shell to clearly indicate the
      functionality is for manual interaction only.<br>
      <br>
      Best Regards,<br>
      Michael<br>
      <br>
      On 3/23/21 5:45 AM, Ulf Wiger wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CADPRLo_-pL8ozCVSAuYRiL5Yj6qwoZP=__uTV5PfUXPsT09jYQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html;
        charset=windows-1252">
      <div dir="ltr">Permissions are a bit tricky. :)
        <div><br>
        </div>
        <div>The issue I encountered was the use of
          `application:ensure_all_started()` in `rebar3 shell`, which I
          think is perfectly appropriate use of the function.</div>
        <div>But if that use is supposed to mimic the starting of
          applications via a boot script, then it should either return
          `ok` (counter-intuitive), or hang until the permission flag(s)
          turn to true.</div>
        <div><br>
        </div>
        <div>The `application:close()` function should definitely remove
          the corresponding entries in `start_p_false`, and if there are
          such entries, not complain that the app hasn't been started.</div>
        <div><br>
        </div>
        <div>Basically, once an application has been started, the
          permission flag should toggle it on or off - if you call
          `permit(A, false)` on running application A, it should be
          stopped. A subsequent call to `permit(A, true)` should start
          it again.</div>
        <div><br>
        </div>
        <div>This is why I think it might be better for
          `ensure_all_started()` to hang rather than returning an error
          tuple. Alternatively, that a new function,
          `await_all_started()` does this, if that's what's desired.</div>
        <div>The question then becomes which one 'rebar3 shell` should
          use...</div>
        <div><br>
        </div>
        <div>BR,</div>
        <div>Ulf W</div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, Mar 23, 2021 at 1:13
          PM Fred Hebert <<a href="mailto:mononcqc@ferd.ca"
            moz-do-not-send="true">mononcqc@ferd.ca</a>> wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div dir="ltr">
            <div>I initially implemented
              `application:ensure_all_started/1,2' because it made for
              an easier get-started mechanism than getting a full blown
              release, and avoided having people do the annoying "try
              until it works" garbage routine by hand (which the
              function is now doing), or having to just line up all the
              start calls at the beginning of a test run.</div>
            <div><br>
            </div>
            <div>I would be in favour of just letting it fail and return
              back {error, {b, {permit, false}}} -- there are more
              variations we could use, but this term allows to:</div>
            <div>- specifically mention it's b that isn't allowed to
              start</div>
            <div>- uses the 'permit' keyword that matches the function
              name, such that googling something like "erlang permit
              false" will yield things such as the doc page for
              application:permit/2 (or this thread, given how google
              indexing works)</div>
            <div><br>
            </div>
            <div>That being said, it does not line up with the current
              API usage, which would probably need some fixing of some
              sort? Look at this session:</div>
            <div><br>
            </div>
            <div style="margin-left:40px"><span
                style="font-family:monospace">1>
                application:load(ssl).<br>
                ok<br>
                2> application:permit(ssl, false).<br>
                ok<br>
                3> application:ensure_all_started(crypto).<br>
                {ok,[crypto]}<br>
                4> application:ensure_all_started(public_key).<br>
                {ok,[asn1,public_key]}<br>
                5> application:start(ssl).<br>
                ok<br>
                6> application:stop(ssl).<br>
                {error,{not_started,ssl}} </span><br>
            </div>
            <div><br>
            </div>
            <div>Starting the application "works" even if it does not
              with permissions; the call silently fails while returning
              it succeeded. Since the current documentation for
              ensure_all_started states the following:<br>
              <blockquote class="gmail_quote" style="margin:0px 0px 0px
                0.8ex;border-left:1px solid
                rgb(204,204,204);padding-left:1ex">
                <p>The function reports <span>{error, {AppName,Reason}}</span>
                  for errors, where <span>Reason</span> is any possible
                  reason returned by <span><a
                      href="http://erlang.org/doc/apps/kernel/application.html#start-1"
                      target="_blank" moz-do-not-send="true"><span>start/1,2</span></a></span>
                  when starting a specific dependency.</p>
              </blockquote>
              <div>We are in a situation where ensure_all_started can't
                or won't know that permissions are at play (I didn't
                when I implemented it), and it appears that we would
                need to do an explicit permission check before each run
                to properly return the error explaining the issue
                without breaking the compatibility of start/1,2. The
                gotcha here is that there's apparently no way to access
                this status aside from application_controller internals
                that would need some extra visibility, which start/1,2
                calls on its own as well.</div>
              <div><br>
              </div>
              <div>Regards,</div>
              <div>Fred.<br>
              </div>
            </div>
          </div>
          <br>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">On Mon, Mar 22, 2021 at
              1:06 PM Ulf Wiger <<a href="mailto:ulf@wiger.net"
                target="_blank" moz-do-not-send="true">ulf@wiger.net</a>>
              wrote:<br>
            </div>
            <blockquote class="gmail_quote" style="margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex">
              <div dir="ltr">Hmm, trying some more with OTP 24, it
                addresses the problem with the memory growth, but still
                isn't permission-aware.
                <div><br>
                </div>
                <div>Consider test apps a and b, where a depends on b.</div>
                <div><br>
                </div>
                <div>15> application:permit(b,false).<br>
                  ok<br>
                  16> application:ensure_all_started(a).<br>
                  {error,{a,{not_started,b}}}<br>
                  17> application:which_applications().<br>
                  [{stdlib,"ERTS  CXC 138 10","3.15"},<br>
                   {kernel,"ERTS  CXC 138 10","8.0"}]<br>
                  18> application:permit(b,true).<br>
                  ok<br>
                  19> application:which_applications().<br>
                  [{b,"test app","0.1"},<br>
                   {stdlib,"ERTS  CXC 138 10","3.15"},<br>
                   {kernel,"ERTS  CXC 138 10","8.0"}]<br>
                </div>
                <div><br>
                </div>
                <div>The call to application:ensure_all_started(a)
                  fails, and supposedly all child apps that were started
                  will have been stopped again, and it does look that
                  way.</div>
                <div><br>
                </div>
                <div>But if we later permit b to run, it turns out that
                  the start request wasn't actually removed, and b pops
                  up.</div>
                <div><br>
                </div>
                <div>This is for sure a much less serious problem than
                  the previous one.</div>
                <div><br>
                </div>
                <div>However, I'm not sure if returning error is
                  actually the right thing to do there. The call SHOULD
                  probably hang.</div>
                <div><br>
                </div>
                <div>Comments?</div>
                <div><br>
                </div>
                <div>BR,</div>
                <div>Ulf W</div>
              </div>
              <br>
              <div class="gmail_quote">
                <div dir="ltr" class="gmail_attr">On Mon, Mar 22, 2021
                  at 1:23 PM Ulf Wiger <<a
                    href="mailto:ulf@wiger.net" target="_blank"
                    moz-do-not-send="true">ulf@wiger.net</a>> wrote:<br>
                </div>
                <blockquote class="gmail_quote" style="margin:0px 0px
                  0px 0.8ex;border-left:1px solid
                  rgb(204,204,204);padding-left:1ex">
                  <div dir="ltr">When I started looking closer into
                    this, it would appear as if there is a long-standing
                    bug in the application_controller regarding
                    permissions.
                    <div><br>
                    </div>
                    <div>And with "long-standing" I mean that it was
                      there even when Kostis did some Tidier-based
                      cleanup 11 years ago. Kostis didn't introduce it,
                      though.</div>
                    <div><br>
                    </div>
                    <div>When servicing a start request, the
                      application_controller, if permission(App) ==
                      false, adds a new entry to the `start_p_false`
                      list, i.e. a new entry for each request.</div>
                    <div><a
href="https://github.com/erlang/otp/blob/master/lib/kernel/src/application_controller.erl#L689-L690"
                        target="_blank" moz-do-not-send="true">https://github.com/erlang/otp/blob/master/lib/kernel/src/application_controller.erl#L689-L690</a><br>
                    </div>
                    <div><br>
                    </div>
                    <div>... but when servicing a subsequent
                      {permit_application, App, true}, it uses
                      lists:keydelete/3 to remove the App from the
                      `start_p_false` list.</div>
                    <div><a
href="https://github.com/erlang/otp/blob/master/lib/kernel/src/application_controller.erl#L759-L761"
                        target="_blank" moz-do-not-send="true">https://github.com/erlang/otp/blob/master/lib/kernel/src/application_controller.erl#L759-L761</a><br>
                    </div>
                    <div><br>
                    </div>
                    <div>lists:keydelete/3 obviously only removes the
                      first matching entry.</div>
                    <div><br>
                    </div>
                    <div>Earlier in that function, it also only locates
                      the first pending request (or rather,
                      chronologically the last), and uses the `From` in
                      `spawn_starter()'.</div>
                    <div><br>
                    </div>
                    <div>The rest of the pending requests should be
                      handled somewhere - likely in
                      `handle_application_started/3`, but aren't.</div>
                    <div><br>
                    </div>
                    <div>BR,</div>
                    <div>Ulf W</div>
                  </div>
                  <br>
                  <div class="gmail_quote">
                    <div dir="ltr" class="gmail_attr">On Sat, Mar 20,
                      2021 at 1:45 PM Mikael Pettersson <<a
                        href="mailto:mikpelinux@gmail.com"
                        target="_blank" moz-do-not-send="true">mikpelinux@gmail.com</a>>
                      wrote:<br>
                    </div>
                    <blockquote class="gmail_quote" style="margin:0px
                      0px 0px 0.8ex;border-left:1px solid
                      rgb(204,204,204);padding-left:1ex">On Sat, Mar 20,
                      2021 at 8:46 AM Ulf Wiger <<a
                        href="mailto:ulf@wiger.net" target="_blank"
                        moz-do-not-send="true">ulf@wiger.net</a>>
                      wrote:<br>
                      ><br>
                      > I had the brilliant idea of using application
                      permissions for a particular use case. This seemed
                      to work perfectly, until I ran `rebar3 shell`, and
                      spotted some disturbing behavior.<br>
                      ><br>
                      > The bug, apparently, lies in that
                      `application:ensure_all_started(A)` ends up
                      busy-looping if A depends on B, and permission(B)
                      -> false. What's worse, for each call to
                      start(B), the application controller notices the
                      permission flag, returns `ok` and inserts an entry
                      in its internal `start_p_false` list. This amounts
                      to a memory leak.<br>
                      ><br>
                      > I commented it in a tweet, then decided to
                      try to find the source, esp. since I suspected
                      `application:ensure_all_started/1`.<br>
                      ><br>
                      > <a
                        href="https://twitter.com/uwiger/status/1372944356781531136"
                        rel="noreferrer" target="_blank"
                        moz-do-not-send="true">https://twitter.com/uwiger/status/1372944356781531136</a><br>
                      ><br>
                      > In short, if permission(B) -> false, what
                      happens is:<br>
                      > start(A) -> {error, {not_started, B}}<br>
                      > start(B) -> ok<br>
                      > start(A) -> {error,  {not_started, B}}<br>
                      > ... [repeat endlessly]<br>
                      ><br>
                      > Now, it could be fixed by adding a permission
                      check in the looping function, but this raises the
                      question of what should happen in the above case.
                      Three alternatives:<br>
                      ><br>
                      > 1. ensure_all_started(A) returns {error,
                      {not_permitted, B}}, or something<br>
                      > 2. the call hangs until the flag(s) change,
                      but start(B) is only called once.<br>
                      > 3. Warn against the use of permissions in the
                      docs, and deprecate them.<br>
                      ><br>
                      > I'm assuming that most of you may not even
                      know about permissions. They were introduced back
                      in 1996-97 (I believe), when I and Martin
                      Björklund were going back and forth on how to
                      support distributed applications and cluster
                      control. Eventually, this led to dist_ac and the
                      protocol being defined, so that users could write
                      a controller app taking control of an application
                      and giving instructions on where it should run. In
                      the AXD301, this was done by the RCM application.
                      I believe I talked about it at the EUC 1997, but
                      it's hard to find information about that on the
                      web. :)<br>
                      ><br>
                      > Anyway, permissions were left in the API, and
                      ARE documented.<br>
                      ><br>
                      > Thoughts?<br>
                      <br>
                      I know we've used the permissions mechanism
                      occasionally during<br>
                      maintenance or live upgrades. Off-hand I don't
                      know if we'd want<br>
                      alternative 1 or 2 (my colleague Daniel Szoboszlay
                      might know more<br>
                      about this).<br>
                      <br>
                      /Mikael<br>
                    </blockquote>
                  </div>
                </blockquote>
              </div>
            </blockquote>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>