1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Improved process handling

This commit is contained in:
Klaus Schmidinger 2000-04-24 13:54:23 +02:00
parent 61a20a36de
commit 8a84f6b751
5 changed files with 64 additions and 40 deletions

View File

@ -4,18 +4,16 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.c 1.6 2000/04/24 09:44:19 kls Exp $ * $Id: dvbapi.c 1.7 2000/04/24 13:27:38 kls Exp $
*/ */
#include "dvbapi.h" #include "dvbapi.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "interface.h" #include "interface.h"
#include "tools.h" #include "tools.h"
@ -59,7 +57,6 @@
#define RESUMEFILESUFFIX "/resume.vdr" #define RESUMEFILESUFFIX "/resume.vdr"
#define RECORDFILESUFFIX "/%03d.vdr" #define RECORDFILESUFFIX "/%03d.vdr"
#define RECORDFILESUFFIXLEN 20 // some additional bytes for safety... #define RECORDFILESUFFIXLEN 20 // some additional bytes for safety...
#define MAXPROCESSTIMEOUT 3 // seconds
// The number of frames to back up when resuming an interrupted replay session: // The number of frames to back up when resuming an interrupted replay session:
#define RESUMEBACKUP (10 * FRAMESPERSEC) #define RESUMEBACKUP (10 * FRAMESPERSEC)
@ -554,7 +551,7 @@ private:
public: public:
cRecordBuffer(int *InFile, const char *FileName); cRecordBuffer(int *InFile, const char *FileName);
virtual ~cRecordBuffer(); virtual ~cRecordBuffer();
int WriteWithTimeout(void); int WriteWithTimeout(bool EndIfEmpty = false);
}; };
cRecordBuffer::cRecordBuffer(int *InFile, const char *FileName) cRecordBuffer::cRecordBuffer(int *InFile, const char *FileName)
@ -720,13 +717,13 @@ int cRecordBuffer::Write(int Max)
return 0; return 0;
} }
int cRecordBuffer::WriteWithTimeout(void) int cRecordBuffer::WriteWithTimeout(bool EndIfEmpty)
{ {
int w, written = 0; int w, written = 0;
int t0 = time_ms(); int t0 = time_ms();
while ((w = Write()) > 0 && time_ms() - t0 < MAXRECORDWRITETIME) while ((w = Write()) > 0 && time_ms() - t0 < MAXRECORDWRITETIME)
written += w; written += w;
return w < 0 ? w : written; return w < 0 ? w : (written == 0 && EndIfEmpty ? -1 : written);
} }
// --- cReplayBuffer --------------------------------------------------------- // --- cReplayBuffer ---------------------------------------------------------
@ -841,7 +838,7 @@ void cReplayBuffer::SkipSeconds(int Seconds)
} }
Index += Seconds * FRAMESPERSEC; Index += Seconds * FRAMESPERSEC;
if (Index < 0) if (Index < 0)
Index = 1; Index = 1; // not '0', to allow GetNextIFrame() below to work!
uchar FileNumber; uchar FileNumber;
int FileOffset; int FileOffset;
if (index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) >= 0) if (index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) >= 0)
@ -1226,35 +1223,17 @@ bool cDvbApi::SetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Sr
return false; return false;
} }
void cDvbApi::KillProcess(pid_t pid)
{
pid_t Pid2Wait4 = pid;
for (time_t t0 = time(NULL); time(NULL) - t0 < MAXPROCESSTIMEOUT; ) {
int status;
pid_t pid = waitpid(Pid2Wait4, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return;
}
if (pid == Pid2Wait4)
return;
}
esyslog(LOG_ERR, "ERROR: process %d won't end (waited %d seconds) - terminating it...", Pid2Wait4, MAXPROCESSTIMEOUT);
if (kill(Pid2Wait4, SIGTERM) < 0) {
esyslog(LOG_ERR, "ERROR: process %d won't terminate (%s) - killing it...", Pid2Wait4, strerror(errno));
if (kill(Pid2Wait4, SIGKILL) < 0)
esyslog(LOG_ERR, "ERROR: process %d won't die (%s) - giving up", Pid2Wait4, strerror(errno));
}
}
bool cDvbApi::Recording(void) bool cDvbApi::Recording(void)
{ {
if (pidRecord && !CheckProcess(pidRecord))
pidRecord = 0;
return pidRecord; return pidRecord;
} }
bool cDvbApi::Replaying(void) bool cDvbApi::Replaying(void)
{ {
if (pidReplay && !CheckProcess(pidReplay))
pidReplay = 0;
return pidReplay; return pidReplay;
} }
@ -1305,6 +1284,7 @@ bool cDvbApi::StartRecord(const char *FileName)
dsyslog(LOG_INFO, "start recording process (pid=%d)", getpid()); dsyslog(LOG_INFO, "start recording process (pid=%d)", getpid());
isMainProcess = false; isMainProcess = false;
bool DataStreamBroken = false;
int fromMain = toRecordPipe[0]; int fromMain = toRecordPipe[0];
int toMain = fromRecordPipe[1]; int toMain = fromRecordPipe[1];
cRecordBuffer *Buffer = new cRecordBuffer(&videoDev, FileName); cRecordBuffer *Buffer = new cRecordBuffer(&videoDev, FileName);
@ -1317,21 +1297,26 @@ bool cDvbApi::StartRecord(const char *FileName)
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = 1; timeout.tv_sec = 1;
timeout.tv_usec = 0; timeout.tv_usec = 0;
bool ForceEnd = false;
if (select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0) { if (select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0) {
if (FD_ISSET(videoDev, &set)) { if (FD_ISSET(videoDev, &set)) {
if (Buffer->Read() < 0) if (Buffer->Read() < 0)
break; break;
DataStreamBroken = false;
} }
if (FD_ISSET(fromMain, &set)) { if (FD_ISSET(fromMain, &set)) {
switch (readchar(fromMain)) { switch (readchar(fromMain)) {
case dvbStop: Buffer->Stop(); break; case dvbStop: Buffer->Stop();
break; ForceEnd = DataStreamBroken;
break;
} }
} }
} }
else else {
DataStreamBroken = true;
esyslog(LOG_ERR, "ERROR: video data stream broken"); esyslog(LOG_ERR, "ERROR: video data stream broken");
if (Buffer->WriteWithTimeout() < 0) }
if (Buffer->WriteWithTimeout(ForceEnd) < 0)
break; break;
} }
delete Buffer; delete Buffer;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.h 1.6 2000/04/24 09:44:21 kls Exp $ * $Id: dvbapi.h 1.7 2000/04/24 10:46:47 kls Exp $
*/ */
#ifndef __DVBAPI_H #ifndef __DVBAPI_H
@ -96,7 +96,6 @@ private:
int fromRecord, toRecord; int fromRecord, toRecord;
int fromReplay, toReplay; int fromReplay, toReplay;
void SetReplayMode(int Mode); void SetReplayMode(int Mode);
void KillProcess(pid_t pid);
public: public:
bool Recording(void); bool Recording(void);
// Returns true if we are currently recording. // Returns true if we are currently recording.

38
tools.c
View File

@ -4,13 +4,14 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.5 2000/04/24 09:46:02 kls Exp $ * $Id: tools.c 1.6 2000/04/24 13:54:23 kls Exp $
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include "tools.h" #include "tools.h"
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -134,6 +135,41 @@ bool RemoveFileOrDir(const char *FileName)
return false; return false;
} }
bool CheckProcess(pid_t pid)
{
pid_t Pid2Check = pid;
int status;
pid = waitpid(Pid2Check, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return false;
}
return true;
}
void KillProcess(pid_t pid, int Timeout)
{
pid_t Pid2Wait4 = pid;
for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
int status;
pid_t pid = waitpid(Pid2Wait4, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return;
}
if (pid == Pid2Wait4)
return;
}
esyslog(LOG_ERR, "ERROR: process %d won't end (waited %d seconds) - terminating it...", Pid2Wait4, Timeout);
if (kill(Pid2Wait4, SIGTERM) < 0) {
esyslog(LOG_ERR, "ERROR: process %d won't terminate (%s) - killing it...", Pid2Wait4, strerror(errno));
if (kill(Pid2Wait4, SIGKILL) < 0)
esyslog(LOG_ERR, "ERROR: process %d won't die (%s) - giving up", Pid2Wait4, strerror(errno));
}
}
// --- cListObject ----------------------------------------------------------- // --- cListObject -----------------------------------------------------------
cListObject::cListObject(void) cListObject::cListObject(void)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.5 2000/04/24 09:46:05 kls Exp $ * $Id: tools.h 1.6 2000/04/24 13:09:20 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -13,6 +13,8 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <syslog.h> #include <syslog.h>
#include <sys/wait.h>
#include <sys/types.h>
extern int SysLogLevel; extern int SysLogLevel;
@ -24,6 +26,7 @@ extern int SysLogLevel;
#define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno)); #define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno));
#define SECSINDAY 86400 #define SECSINDAY 86400
#define MAXPROCESSTIMEOUT 3 // seconds
#define DELETENULL(p) (delete (p), p = NULL) #define DELETENULL(p) (delete (p), p = NULL)
@ -36,6 +39,8 @@ int time_ms(void);
void delay_ms(int ms); void delay_ms(int ms);
bool MakeDirs(const char *FileName, bool IsDirectory = false); bool MakeDirs(const char *FileName, bool IsDirectory = false);
bool RemoveFileOrDir(const char *FileName); bool RemoveFileOrDir(const char *FileName);
bool CheckProcess(pid_t pid);
void KillProcess(pid_t pid, int Timeout = MAXPROCESSTIMEOUT);
class cListObject { class cListObject {
private: private:

3
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * The project's page is at http://www.cadsoft.de/people/kls/vdr
* *
* $Id: vdr.c 1.11 2000/04/24 10:33:38 kls Exp $ * $Id: vdr.c 1.12 2000/04/24 13:36:39 kls Exp $
*/ */
#include <signal.h> #include <signal.h>
@ -183,7 +183,6 @@ int main(int argc, char *argv[])
isyslog(LOG_INFO, "caught signal %d", Interrupted); isyslog(LOG_INFO, "caught signal %d", Interrupted);
DvbApi.StopRecord(); DvbApi.StopRecord();
DvbApi.StopReplay(); DvbApi.StopReplay();
//TODO kill any remaining sub-processes!
isyslog(LOG_INFO, "exiting"); isyslog(LOG_INFO, "exiting");
closelog(); closelog();
return 0; return 0;