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:
parent
61a20a36de
commit
8a84f6b751
51
dvbapi.c
51
dvbapi.c
@ -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();
|
||||||
|
ForceEnd = DataStreamBroken;
|
||||||
break;
|
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;
|
||||||
|
3
dvbapi.h
3
dvbapi.h
@ -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
38
tools.c
@ -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)
|
||||||
|
7
tools.h
7
tools.h
@ -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
3
vdr.c
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user