Guard test pid/1 allows invalid Pid into spawned program

Roger Price <>
Wed Dec 15 15:59:42 CET 2004


I wrote function test/0 to spawn another process and run function
hello/1 in that process.  hello/1 does nothing but print a debugging
message which displays the current processes.

I tested this by entering test:test() on the command line - all went well
and the expected debugging messages were written.  I also ran the test
using apply(test,test,[]) and all went well again.

Finally I ran spawn(test,test,[]) and argument passed to function hello/1
disappeared.

The Pid which I pass to hello/1 as an argument, is invalid even though I
have a guard test pid/1, and the Pid satisfies it.
lists:member(Pid,processes()) gives true before and after the spawn but
false within the spawned program.

If I print hello/1's debug message twice, I see that the list of current
processes changes, with the argument absent from the second message.

I use R9C-1 on a 1GHz PC under SuSE Linux 8.1.  I attach, with my
apologies for a long post, the functions test/0 and hello/1.

Here is a slightly edited trace of the test:

:/tmp> erlc -W test.erl
:/tmp> erlc -W hello.erl
:/tmp> erl
Erlang (BEAM) emulator version 5.3.6.2 [source] [hipe]

Eshell V5.3.6.2  (abort with ^G)
1> % apply/3 produces the correct output
1> apply(test,test,[]) .
test/0 opened LogStream.  Processes:
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>]
checkPid 'LogStream before spawn' succeeds for pid <0.31.0>.
spawn(hello,hello,[<0.31.0>]) -> <0.32.0>.
checkPid 'LogStream after spawn' succeeds for pid <0.31.0>.
ok
hello/1 starts with processes
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>,<0.32.0>]
hello/1 continues with processes
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>,<0.32.0>,<0.33.0>]
checkPid 'Spawned LogStream' succeeds for pid <0.31.0>.

2> % spawn/3 fails
2> spawn(test,test,[]) .
<0.34.0>
test/0 opened LogStream.  Processes:
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>,<0.34.0>, <0.35.0>,<0.36.0>]
checkPid 'LogStream before spawn' succeeds for pid <0.35.0>.
spawn(hello,hello,[<0.35.0>]) -> <0.37.0>.
checkPid 'LogStream after spawn' succeeds for pid <0.35.0>.
hello/1 starts with processes
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>,<0.34.0>,<0.35.0>,<0.36.0>,
 <0.37.0>]
hello/1 continues with processes
[...,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.31.0>,<0.36.0>,<0.37.0>]
checkPid 'Spawned LogStream' fails for pid <0.35.0>.

Note in the "spawn/3" test how <0.35.0> vanishes from the list of
processes, while hello/1 is running.

Roger

%% test.erl

-module(test).
-export([checkPid/2,pp/1,test/0]).

test() ->
   LogFile = '/tmp/hello.log',
   {ok,LogStream} = file:open(LogFile,[append]),

   pp("test/0 opened LogStream.  Processes:"),
   checkPid('LogStream before spawn',LogStream),

   ProgPid = spawn(hello, hello, [LogStream]),

   io:format("spawn(hello,hello,~p) -> ~p.~n", [[LogStream],ProgPid]),
   checkPid('LogStream after spawn',LogStream),
   ok .

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Check that a given pid is for a known process.
checkPid(What,Pid) when atom(What), pid(Pid) ->
  case lists:member(Pid,processes()) of
     true -> io:format("checkPid ~p succeeds for pid ~p.~n",
                       [What,Pid]),
             true;
     _    -> io:format("checkPid ~p fails for pid ~p.~n",
                       [What,Pid]),
             exit(What)
  end;
checkPid(Bad1,Bad2) ->
   io:format("Error in pint:checkPid(~p,~p)~n", [Bad1,Bad2]),
   exit('checkPid') .

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Not very pretty printer for processes.
pp(Prefix) -> io:format("~s [~s]~n", [Prefix,ppPr(processes())]) .
ppPr([])     -> "";
ppPr([P])    -> io_lib:format("~p", [P]);
ppPr([P|Ps]) -> io_lib:format("~p,~s", [P,ppPr(Ps)]) .

%% End of module test

%% hello.erl

-module(hello).
-export([hello/1]).

hello(LogStream) when pid(LogStream) ->
   test:pp("hello/1 starts with processes"),
   test:pp("hello/1 continues with processes"),
   test:checkPid('Spawned LogStream',LogStream),
   yessir .

%% End of module hello





More information about the erlang-questions mailing list