126
126
case Proc#proc.status of
129
AttPid,Pid,Proc#proc.info,Proc#proc.exit_info],
130
Meta = spawn_link(dbg_imeta, exit_info, Args),
129
AttPid,Pid,Proc#proc.info,
130
Proc#proc.exit_info],
131
Meta = spawn_link(dbg_ieval, exit_info, Args),
131
132
Proc2 = Proc#proc{meta=Meta, attpid=AttPid},
132
133
Procs = lists:keyreplace(Pid, #proc.pid,
133
134
State#state.procs, Proc2),
134
{reply, {ok, Meta}, State#state{procs=Procs}};
135
{reply, {ok,Meta}, State#state{procs=Procs}};
136
send(Proc#proc.meta, {attached, AttPid}),
137
Meta = Proc#proc.meta,
138
send(Meta, {attached, AttPid}),
137
139
Procs = lists:keyreplace(Pid, #proc.pid,
138
140
State#state.procs,
139
141
Proc#proc{attpid=AttPid}),
140
{reply, {ok, Proc#proc.meta}, State#state{procs=Procs}}
142
{reply, {ok, Meta}, State#state{procs=Procs}}
144
_AttPid -> % there is already an attached process
143
145
{reply, error, State}
194
196
%% A new, debugged process has been started. Return its status,
195
%% ie running (running as usual) or init_break (stop)
197
%% ie running (running as usual) or break (stop)
196
198
%% The status depends on if the process is automatically attached to
198
200
Reply = case auto_attach(init, State#state.auto, Pid) of
199
AttPid when pid(AttPid) -> init_break;
201
AttPid when pid(AttPid) -> break;
200
202
ignore -> running
203
205
%% Do not add AttPid, it should call attached/2 when started instead
204
206
Proc = #proc{pid=Pid, meta=Meta, status=running, function=Function},
205
send_all(subscriber, {new_process, {Pid,Function,running,{}}}, State),
208
{new_process, {Pid,Function,running,{}}}, State),
207
210
{reply, Reply, State#state{procs=State#state.procs++[Proc]}};
382
386
Proc2 = Proc#proc{status=Status, info=Info},
383
387
{noreply, State#state{procs=lists:keyreplace(Meta, #proc.meta,
384
388
State#state.procs, Proc2)}};
389
handle_cast({set_exit_info, Meta, ExitInfo}, State) ->
390
{true, Proc} = get_proc({meta, Meta}, State#state.procs),
391
Procs = lists:keyreplace(Meta, #proc.meta, State#state.procs,
392
Proc#proc{exit_info=ExitInfo}),
393
{noreply,State#state{procs=Procs}};
387
396
handle_cast({delete, Mod}, State) ->
410
420
false -> ignore % pid may have exited
416
send_all([subscriber, attached], {no_interpret, Mod}, State),
418
%% Remove all breakpoints for Mod
419
handle_cast({no_break, Mod}, State).
425
send_all([subscriber,attached], {no_interpret, Mod}, State),
427
%% Remove all breakpoints for Mod
428
handle_cast({no_break, Mod}, State)
422
handle_info({'EXIT', Who, Why}, State) ->
432
handle_info({'EXIT',Who,Why}, State) ->
423
433
case get_proc({meta, Who}, State#state.procs) of
435
%% Exited process is a meta process for exit_info
436
{true,#proc{status=exit}} ->
425
439
%% Exited process is a meta process
426
{true, Proc} when Proc#proc.status/=exit ->
427
441
Pid = Proc#proc.pid,
429
%% Extract information from the exit reason
430
{Info, ExitInfo} = case Why of
431
{Who, Reason} -> {Reason, {}};
432
{Who, Reason, Where, Bs, Stack} ->
433
{Reason, {Where, Bs, Stack}};
437
%% Check if a new meta process should be started, i.e. if
438
%% someone is attached to the debugged process
442
ExitInfo = Proc#proc.exit_info,
443
%% Check if someone is attached to the debugged process,
444
%% if so a new meta process should be started
439
445
Meta = case Proc#proc.attpid of
440
446
AttPid when pid(AttPid) ->
442
AttPid, Proc#proc.pid, Info, ExitInfo],
443
spawn_link(dbg_imeta, exit_info, Args);
447
spawn_link(dbg_ieval, exit_info,
448
[self(),AttPid,Pid,Why,ExitInfo]);
445
450
%% Otherwise, auto attach if necessary
446
451
auto_attach(exit, State#state.auto, Pid),
450
send_all(subscriber, {new_status, Pid, exit, Info}, State),
452
Proc2 = Proc#proc{meta=Meta, status=exit, info=Info,
454
send_all(subscriber, {new_status,Pid,exit,Why}, State),
454
455
Procs = lists:keyreplace(Who, #proc.meta, State#state.procs,
456
{noreply, State#state{procs=Procs}};
459
{noreply,State#state{procs=Procs}};
458
%% Exited process is a simple meta process for a terminated process
459
{true, Proc} when Proc#proc.status==exit ->
463
462
case get_proc({attpid, Who}, State#state.procs) of
465
464
%% Exited process is an attached process
468
466
%% If status==exit, then the meta process is a
469
467
%% simple meta for a terminated process and can be
470
%% terminated as well (it is only needed by the attached
468
%% terminated as well (it is only needed by
469
%% the attached process)
472
470
case Proc#proc.status of
473
471
exit -> send(Proc#proc.meta, stop);
474
_Status -> send(Proc#proc.meta, {detached, Who})
472
_Status -> send(Proc#proc.meta, detached)
477
474
Procs = lists:keyreplace(Proc#proc.pid, #proc.pid,
478
475
State#state.procs,
479
476
Proc#proc{attpid=undefined}),