[mythtv] [patch] channelbase cleanup
Daniel Thor Kristjansson
danielk at mrl.nyu.edu
Wed Dec 29 19:19:14 UTC 2004
This patch cleans up the handling of errors encountered when executing
an external channel changing program or script. I've also added some
code to timeout if this program does not exit within 30 seconds. However
I've left in the "&" in the execution of the script because this
function is not called in a separate thread and could possibly take a
very long time when changing the channel involves moving a dish. But if
we address this problem in the future, this timeout handling would allow
us to wait for the tuning program to finish, and let us observe the
return value; this lets the external program signal problems to MythTV.
This function was returning 'no error' when the fork call didn't work,
this has been fixed. I've also added a check of the return value of
execl, which will tell us if there was an access error. And I've fixed
the status checking so it differentiates between a program killed by a
signal or returning a non-zero value. This patch also changes the cerr
redirects and perror's in channelbase to use the VERBOSE macro.
-- Daniel
-------------- next part --------------
Index: libs/libmythtv/channelbase.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channelbase.cpp,v
retrieving revision 1.9
diff -u -r1.9 channelbase.cpp
--- libs/libmythtv/channelbase.cpp 19 Aug 2004 02:02:20 -0000 1.9
+++ libs/libmythtv/channelbase.cpp 29 Dec 2004 19:05:15 -0000
@@ -107,7 +107,8 @@
if (input >= 0)
SwitchToInput(input, true);
else
- cerr << "Couldn't find input: " << inputname << " on card\n";
+ VERBOSE(VB_IMPORTANT, QString("ChannelBase: Could not find input: "
+ "%1 on card\n").arg(inputname));
}
void ChannelBase::SwitchToInput(const QString &inputname, const QString &chan)
@@ -120,7 +121,9 @@
SetChannelByString(chan);
}
else
- cerr << "Couldn't find input: " << inputname << " on card\n";
+ VERBOSE(VB_IMPORTANT,
+ QString("ChannelBase: Could not find input: %1 on card when "
+ "setting channel %2\n").arg(inputname).arg(chan));
}
bool ChannelBase::ChangeExternalChannel(const QString &channum)
@@ -134,28 +137,73 @@
VERBOSE(VB_CHANNEL, QString("External channel change: %1").arg(command));
pid_t child = fork();
if (child < 0)
- {
- perror("fork");
+ { // error encountered in creating fork
+ QString msg("ChannelBase: fork error -- ");
+ msg.append(strerror(errno));
+ VERBOSE(VB_IMPORTANT, msg);
+ return false;
}
else if (child == 0)
- {
+ { // we are the new fork
for(int i = 3; i < sysconf(_SC_OPEN_MAX) - 1; ++i)
close(i);
- execl("/bin/sh", "sh", "-c", command.ascii(), NULL);
- perror("exec");
- _exit(-11);
+ int ret=execl("/bin/sh", "sh", "-c", command.ascii(), NULL);
+ QString msg("ChannelBase: ");
+ if (EACCES==ret) {
+ msg.append(QString("Access denied to /bin/sh"
+ " when executing %1\n").arg(command.ascii()));
+ }
+ msg.append(strerror(errno));
+ VERBOSE(VB_IMPORTANT, msg);
+ _exit(1); // this exit is ok, we are just exiting from the channel changing fork with an error.
}
else
- {
- int status;
- if (waitpid(child, &status, 0) < 0)
+ { // child contains the pid of the new process
+ int status=0, pid=0;
+ VERBOSE(VB_CHANNEL, "Waiting for External Tuning program to exit");
+
+ bool timed_out = false;
+ uint timeout = 30; // how long to wait in seconds
+ time_t start_time = time(0);
+ while (-1!=pid && !timed_out)
{
- perror("waitpid");
+ sleep(1);
+ pid = waitpid(child, &status, WUNTRACED|WNOHANG);
+ VERBOSE(VB_IMPORTANT, QString("ret_pid(%1) child(%2) status(0x%3)")
+ .arg(pid).arg(child).arg(status,0,16));
+ if (pid==child)
+ break;
+ else if (time(0)>start_time+timeout)
+ timed_out = true;
}
- else if (status != 0)
+ if (timed_out)
{
- cerr << "External channel change command exited with status "
- << status << endl;
+ VERBOSE(VB_IMPORTANT, "External Tuning program timed out, killing");
+ kill(child, SIGTERM);
+ usleep(500);
+ kill(child, SIGKILL);
+ return false;
+ }
+
+ VERBOSE(VB_CHANNEL, "External Tuning program no longer running");
+ if (WIFEXITED(status))
+ { // program exited normally
+ int ret = WEXITSTATUS(status);
+ if (ret)
+ { // external tuning program returned error value
+ VERBOSE(VB_IMPORTANT,
+ QString("ChannelBase: external tuning program "
+ "exited with error %1").arg(ret));
+ return false;
+ }
+ VERBOSE(VB_IMPORTANT, "External Tuning program exited with no error");
+ }
+ else
+ { // program exited abnormally
+ QString msg = QString("ChannelBase: external tuning program "
+ "encountered error %1 -- ").arg(errno);
+ msg.append(strerror(errno));
+ VERBOSE(VB_IMPORTANT, msg);
return false;
}
}
More information about the mythtv-dev
mailing list