Current section
Files
Jump to
Current section
Files
src/edb_gatekeeper.erl
%% Copyright (c) Meta Platforms, Inc. and affiliates.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% % @format
%%
%% Ephemeral gen_server that waits for a freshly launched debuggee node
%% to reverse-attach
-module(edb_gatekeeper).
%% erlfmt:ignore
% @fb-only
-compile(warn_missing_spec_all).
-moduledoc false.
-behavior(gen_server).
%% Public API
-export([new/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2]).
%% -------------------------------------------------------------------
%% Types
%% -------------------------------------------------------------------
-export_type([id/0]).
-opaque id() :: integer().
-type state() :: id().
%% -------------------------------------------------------------------
%% Public API
%% -------------------------------------------------------------------
-spec new() -> {ok, Id, CallGatekeeperCode} when
Id :: id(),
CallGatekeeperCode :: binary().
new() when node() /= 'nonode@nohost' ->
Id = erlang:unique_integer([positive]),
GatekeeperName = binary_to_atom(list_to_binary(io_lib:format("edb-~p", [Id]))),
{ok, _Pid} = gen_server:start(
{local, GatekeeperName},
?MODULE,
Id,
[]
),
#{name_domain := NameDomain} = net_kernel:get_state(),
CallGatekeeperCode = io_lib:format(
~"""
case net_kernel:get_state() of
#{started := no} -> {ok, _} = net_kernel:start(undefined, #{name_domain => ~p});
_ -> ok
end,
erlang:set_cookie(~p, ~p),
true = net_kernel:connect_node(~p),
ok = gen_server:call({~p, ~p}, [])
""",
[
NameDomain,
node(),
erlang:get_cookie(),
node(),
GatekeeperName,
node()
]
),
SingleLine = iolist_to_binary(re:replace(CallGatekeeperCode, "\\n", " ", [global])),
{ok, Id, SingleLine}.
%% -------------------------------------------------------------------
%% gen_server callbacks
%% -------------------------------------------------------------------
-spec init(Id) -> {ok, state()} when Id :: id().
init(Id) ->
State0 = Id,
{ok, State0}.
-spec handle_call([], From, state()) -> {stop, normal, state()} when
From :: gen_server:from().
handle_call([], From, State = Id) ->
{ClientPid, _ReplayTag} = From,
DebuggeeNode = node(ClientPid),
ok = edb_node_monitor:reverse_attach_notification(Id, DebuggeeNode),
gen_server:reply(From, ok),
{stop, normal, State}.
-spec handle_cast(term(), state()) -> {noreply, state()}.
handle_cast(_, State) ->
{noreply, State}.