Update unix postprocessor code to allow for a fixed number of simultaneous postprocessor child processes. Previous behavior killed the previous process in order to start a new one. Also correctly tracks when they die.

pull/68/head
Jeffery Weston 2022-04-29 13:47:07 -04:00
parent 5dc78909ce
commit b997771fec
1 changed files with 87 additions and 19 deletions

View File

@ -81,37 +81,49 @@ bool NetscapeIsRunning(Window *result);
bool NetscapeCheckWindow(Window window); bool NetscapeCheckWindow(Window window);
#endif // NETSCAPE_SUPPORT #endif // NETSCAPE_SUPPORT
#define MAX_SUBPROCESSES 32
static void OnSIGCHLD(int signum);
class UnixPostProcessor : public NormPostProcessor class UnixPostProcessor : public NormPostProcessor
{ {
public: public:
~UnixPostProcessor(); ~UnixPostProcessor();
bool IsActive() {return (0 != process_id);} bool IsActive();
bool ProcessFile(const char* path); bool ProcessFile(const char* path);
void Kill(); void Kill();
void OnSIGCHLD(); void ClearPid(int pid);
private: private:
friend class NormPostProcessor; friend class NormPostProcessor;
UnixPostProcessor(); UnixPostProcessor();
bool IsActive(unsigned int array_element);
unsigned int GetOpenProcessIdSlot();
void Kill(unsigned int array_element);
int process_id; int process_id[MAX_SUBPROCESSES];
#ifdef NETSCAPE_SUPPORT #ifdef NETSCAPE_SUPPORT
Window window_id; Window window_id;
#endif // NETSCAPE_SUPPORT #endif // NETSCAPE_SUPPORT
}; // end class UnixPostProcessor }; // end class UnixPostProcessor
UnixPostProcessor* theprocessor;
UnixPostProcessor::UnixPostProcessor() UnixPostProcessor::UnixPostProcessor()
: process_id(0) : process_id()
#ifdef NETSCAPE_SUPPORT #ifdef NETSCAPE_SUPPORT
,window_id(0) ,window_id(0)
#endif // NETSCAPE_SUPPORT #endif // NETSCAPE_SUPPORT
{ {
signal(SIGCHLD, OnSIGCHLD);
} }
NormPostProcessor* NormPostProcessor::Create() NormPostProcessor* NormPostProcessor::Create()
{ {
return static_cast<NormPostProcessor*>(new UnixPostProcessor); //return static_cast<NormPostProcessor*>(new UnixPostProcessor);
theprocessor = new UnixPostProcessor;
return static_cast<NormPostProcessor*>(theprocessor);
} // end NormPostProcessor::Create() } // end NormPostProcessor::Create()
UnixPostProcessor::~UnixPostProcessor() UnixPostProcessor::~UnixPostProcessor()
@ -119,6 +131,31 @@ UnixPostProcessor::~UnixPostProcessor()
if (IsActive()) Kill(); if (IsActive()) Kill();
} }
bool UnixPostProcessor::IsActive()
{
for (unsigned int i=0;i<MAX_SUBPROCESSES;i++)
{
if (0 != process_id[i]) return true;
}
return false;
}
bool UnixPostProcessor::IsActive(unsigned int array_element)
{
return (0 != process_id[array_element]);
}
unsigned int UnixPostProcessor::GetOpenProcessIdSlot()
{
for (unsigned int i=0;i<MAX_SUBPROCESSES;i++)
{
if (0 == process_id[i]) return i;
}
//No available slot, kill something
Kill(0);
return 0;
}
bool UnixPostProcessor::ProcessFile(const char* path) bool UnixPostProcessor::ProcessFile(const char* path)
{ {
const char** argv = (const char**)process_argv; const char** argv = (const char**)process_argv;
@ -192,7 +229,7 @@ bool UnixPostProcessor::ProcessFile(const char* path)
} }
else else
{ {
if (IsActive()) Kill(); //if (IsActive()) Kill();
window_id = USE_ACTIVE_WINDOW; window_id = USE_ACTIVE_WINDOW;
myArgs[i++] = path; myArgs[i++] = path;
} // end if/else (NetscapeIsRunning()) } // end if/else (NetscapeIsRunning())
@ -203,7 +240,8 @@ bool UnixPostProcessor::ProcessFile(const char* path)
else else
#endif // NETSCAPE_SUPPORT #endif // NETSCAPE_SUPPORT
{ {
if (IsActive()) Kill(); //if (IsActive()) Kill();
// GetOpenProcessIdSlot() below will do this for us now...
argv[argc] = path; argv[argc] = path;
} }
@ -212,11 +250,12 @@ bool UnixPostProcessor::ProcessFile(const char* path)
sighandler_t sigintHandler = signal(SIGINT, SIG_DFL); sighandler_t sigintHandler = signal(SIGINT, SIG_DFL);
sighandler_t sigchldHandler = signal(SIGCHLD, SIG_DFL); sighandler_t sigchldHandler = signal(SIGCHLD, SIG_DFL);
switch((process_id = fork())) unsigned int idnum = GetOpenProcessIdSlot();
switch((process_id[idnum] = fork()))
{ {
case -1: // error case -1: // error
DMSG(0, "UnixPostProcessor::ProcessFile fork() error: %s\n", strerror(errno)); DMSG(0, "UnixPostProcessor::ProcessFile fork() error: %s\n", strerror(errno));
process_id = 0; process_id[idnum] = 0;
process_argv[process_argc] = NULL; process_argv[process_argc] = NULL;
return false; return false;
@ -235,8 +274,8 @@ bool UnixPostProcessor::ProcessFile(const char* path)
signal(SIGINT, sigintHandler); signal(SIGINT, sigintHandler);
// The use of "waitpid()" here is a work-around // The use of "waitpid()" here is a work-around
// for an IRIX SIGCHLD issue // for an IRIX SIGCHLD issue
int status; //int status;
while (waitpid(-1, &status, WNOHANG) > 0); //while (waitpid(-1, &status, WNOHANG) > 0);
signal(SIGCHLD, sigchldHandler); signal(SIGCHLD, sigchldHandler);
break; break;
} }
@ -245,9 +284,17 @@ bool UnixPostProcessor::ProcessFile(const char* path)
void UnixPostProcessor::Kill() void UnixPostProcessor::Kill()
{ {
if (!IsActive()) return; for (unsigned int i=0;i<MAX_SUBPROCESSES;i++)
{
if (IsActive(i)) Kill(i);
}
}
void UnixPostProcessor::Kill(unsigned int array_element)
{
if (!IsActive(array_element)) return;
int count = 0; int count = 0;
while((kill(process_id, SIGTERM) != 0) && count < 10) while((kill(process_id[array_element], SIGTERM) != 0) && count < 10)
{ {
if (errno == ESRCH) break; if (errno == ESRCH) break;
count++; count++;
@ -255,22 +302,43 @@ void UnixPostProcessor::Kill()
} }
count = 0; count = 0;
int status; int status;
while((waitpid(process_id, &status, 0) != process_id) && count < 10) while((waitpid(process_id[array_element], &status, 0) != process_id[array_element]) && count < 10)
{ {
if (errno == ECHILD) break; if (errno == ECHILD) break;
count++; count++;
DMSG(0, "UnixPostProcessor::Kill waitpid() error: %s\n", strerror(errno)); DMSG(0, "UnixPostProcessor::Kill waitpid() error: %s\n", strerror(errno));
} }
process_id = 0; process_id[array_element] = 0;
} // end UnixPostProcessor::Kill() } // end UnixPostProcessor::Kill()
void UnixPostProcessor::OnSIGCHLD() void UnixPostProcessor::ClearPid(int pid)
{
for (unsigned int i=0;i<MAX_SUBPROCESSES;i++)
{
if (pid == process_id[i]) process_id[i] = 0;
}
}
static void OnSIGCHLD(int signum)
{ {
// See if post processor exited itself // See if post processor exited itself
int status; int status;
if (wait(&status) == process_id) process_id = 0; pid_t p;
} // end UnixPostProcessor::HandleSIGCHLD() //int wait_rtn = wait(&status);
while (true)
{
p = waitpid(-1, &status, WNOHANG);
if (p == -1)
{
if (errno == EINTR) continue;
break;
}
// check for no more children
else if (p == 0) break;
// else handle returned PID
theprocessor->ClearPid(p);
}
}
#ifdef NETSCAPE_SUPPORT #ifdef NETSCAPE_SUPPORT
bool CheckForNetscape(const char* cmd) bool CheckForNetscape(const char* cmd)