View Issue Details

IDProjectCategoryView StatusLast Update
0011797FPCFCLpublic2020-09-17 21:56
ReporterBurkhard Carstens Assigned ToJonas Maebe  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformi386OSlinux 
Fixed in Version2.4.0 
Summary0011797: Starting something via TProcess and then closing it leaves a zombie process
DescriptionWhen starting an application via TProcess (e.g. firefox or xterm) and then closing it (by clicking close button of the browser), a zombie process is left.
Steps To ReproduceMethod A:
1. start lazarus
2. click "Help"/"Online Help" menu
3. close the browser
4. check with "ps auxwww|grep defunct"
    --> browser zombie
5. repeat steps 2. to 4.
    --> two browser zombies
6. close lazarus
7. check again with "ps auxwww|grep defunct"
    --> zombies are gone.

Method B
* run attached program
TagsNo tags attached.
Fixed in Revision12923
FPCOldBugId
FPCTarget
Attached Files

Relationships

related to 0035527 new Lazarus openDocument and openURL leave zombie processes 

Activities

2008-08-05 16:32

 

zombie.pas (1,385 bytes)   
program zombie;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this }
  , sysutils
  , process;


procedure RunNewConsole;
var ap : TProcess;
begin
  ap:=TProcess.Create(nil);
  ap.ApplicationName:='running something with poNewConsole';
  ap.CommandLine:='/bin/bash -lc -- ''watch df -h''';
  ap.Options:=[poNewConsole];
  ap.WindowRows:=15;
  ap.WindowColumns:=110;
  ap.Execute;
  sleep(20);
  ap.free;
end;


procedure RunXtermDirect;
var ap : TProcess;
begin
  ap:=TProcess.Create(nil);
  ap.CommandLine:='xterm -title ''running xterm directly'' -geometry 110x15 -e ''watch df -h''';
  ap.Options:=[];
  ap.Execute;
  sleep(20);
  ap.free;
end;

procedure RunFirefox;
var ap : TProcess;
begin
  ap:=TProcess.Create(nil);
  ap.CommandLine:='firefox';
  ap.Options:=[];
  ap.Execute;
  sleep(20);
  ap.free;
end;


begin
  writeln('RunNewConsole .. please close xterm and check with "ps auxwww|grep xterm"');
  writeln('press enter to continue ...');
  RunNewConsole;
  readln;
  writeln('RunXtermDirect .. please close xterm and check with "ps auxwww|grep xterm"');
  writeln('press enter to continue ...');
  RunXtermDirect;
  readln;
  writeln('RunFirefox .. please close firefox and check with "ps auxwww|grep firefox"');
  writeln('press enter to continue ...');
  RunFirefox;
  readln;
end.

zombie.pas (1,385 bytes)   

Burkhard Carstens

2008-08-05 20:29

reporter   ~0021067

Last edited: 2008-08-05 20:30

Seems this is expected behaviour. One must call fpWait to remove the zombie.
This can be solved by either
a) installing a signal handler for SIGCHLD (with flag SA_NOCLDSTOP of course) that calls fpWait or
b) by setting the SA_NOCLDWAIT flag for the SIGCHLD signal.

Both ways unfortunately are not really great, because I also use TProcess.WaitOnExit which then can't deliver the exit status anymore.
( same problem in lazarus, I guess: not interested in results of the online help browser, but needs exit status of e.g. compiler .. )

Burkhard Carstens

2008-08-06 14:03

reporter   ~0021084

Installing a signal handler for SIGCHLD breaks TProcess.WaitOnExit, regardless if wait is called in the handler or not.

var a,b : TProcess;
..
a.execute;
a.free;
b.execute;
b.waitOnExit;

Now if the app started by a is closed, fpWaitPid in b.WaitOnExit returns with -1 and fpGetErrNo returns EINTR.

This can be avoided by adding the SA_RESTART flag to the signal handler but I don't know if this is supported on older/other kernels.
So I assume, the correct way would be to call fpWaitPid again in case of EINTR error?

Function TProcess.WaitOnExit : Boolean;

Var
  R : TPid;//Dword;
  LErr : LongInt;

begin
  repeat
    LErr:=0;
    R:=fpWaitPid(Handle,pcint(@FExitCode),0);
    if R < 0 then
      LErr:=fpGetErrNo;
  until LErr <> ESysEINTR;
  Result:=(R=Handle);
  If Result then
    FExitCode:=WExitStatus(FExitCode);
  FRunning:=False;
end;

Marco van de Voort

2009-01-30 16:55

manager   ~0024895

Looks sane. waitpid can return eintr also on Unix.

Moreover, we should then check our own RTL and handle this properly.

waitprocess seems to handle it ok. For instance Jonas' (newer) libc based pclose implementation seems to use waitprocess, the others not.

Jonas Maebe

2009-03-19 21:16

manager   ~0026250

I've changed waitonexit to use unix.waitprocess(), which handles all corner cases correctly.

Issue History

Date Modified Username Field Change
2008-08-05 16:32 Burkhard Carstens New Issue
2008-08-05 16:32 Burkhard Carstens File Added: zombie.pas
2008-08-05 20:29 Burkhard Carstens Note Added: 0021067
2008-08-05 20:30 Burkhard Carstens Note Edited: 0021067
2008-08-06 14:03 Burkhard Carstens Note Added: 0021084
2009-01-30 16:55 Marco van de Voort Note Added: 0024895
2009-03-19 21:16 Jonas Maebe Fixed in Revision => 12923
2009-03-19 21:16 Jonas Maebe Status new => resolved
2009-03-19 21:16 Jonas Maebe Fixed in Version => 2.3.1
2009-03-19 21:16 Jonas Maebe Resolution open => fixed
2009-03-19 21:16 Jonas Maebe Assigned To => Jonas Maebe
2009-03-19 21:16 Jonas Maebe Note Added: 0026250
2010-03-06 21:03 Jonas Maebe Status resolved => closed
2020-09-17 21:56 Bart Broersma Relationship added related to 0035527