1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-27 04:32:55 +00:00

Fix: conky waited indefinitely on programs started with \$exec-alike vars if those programs don't quit.

Conky now kills the program when it should start the next update, this makes using things like tail with
the -f option possible in a \$exec.

I am not pushing this to 1.7.2 because this is a pretty big change in the code and it is not really
a bugfix but more a usability-problem-fix (if that term would exist).
This commit is contained in:
Nikolas Garofil 2009-07-26 02:26:22 +02:00
parent 4d37d021e1
commit b963c2827f

View File

@ -150,6 +150,7 @@ double update_interval;
double update_interval_old; double update_interval_old;
double update_interval_bat; double update_interval_bat;
void *global_cpu = NULL; void *global_cpu = NULL;
pid_t childpid = 0;
int argc_copy; int argc_copy;
char** argv_copy; char** argv_copy;
@ -639,13 +640,61 @@ static void human_readable(long long num, char *buf, int size)
/* global object list root element */ /* global object list root element */
static struct text_object global_root_object; static struct text_object global_root_object;
//our own implementation of popen, the difference : the value of 'childpid' will be filled with
//the pid of the running 'command'. This is useful if want to kill it it hangs while reading
//or writing to it. We have to kill it because pclose will wait until the process dies by itself
FILE* pid_popen(const char *command, const char *mode, pid_t *child) {
int ends[2];
int parentend, childend;
//by running pipe after the strcmp's we make sure that we don't have to create a pipe
//and close the ends if mode is something illegal
if(strcmp(mode, "r") == 0) {
if(pipe(ends) != 0) {
return NULL;
}
parentend = ends[0];
childend = ends[1];
} else if(strcmp(mode, "w") == 0) {
if(pipe(ends) != 0) {
return NULL;
}
parentend = ends[1];
childend = ends[0];
} else {
return NULL;
}
*child = fork();
if(*child == -1) {
close(parentend);
close(childend);
return NULL;
} else if(*child > 0) {
close(childend);
} else {
//don't read from both stdin and pipe or write to both stdout and pipe
if(childend == ends[0]) {
close(0);
} else {
close(1);
}
dup(childend); //by dupping childend, the returned fd will have close-on-exec turned off
execl("/bin/sh", "sh", "-c", command, (char *) NULL);
_exit(EXIT_FAILURE); //child should die here, (normally execl will take care of this but it can fail)
}
return fdopen(parentend, mode);
}
static inline void read_exec(const char *data, char *buf, const int size) static inline void read_exec(const char *data, char *buf, const int size)
{ {
FILE *fp = popen(data, "r"); FILE *fp = pid_popen(data, "r", &childpid);
if(fp) { if(fp) {
int length = fread(buf, 1, size, fp); int length;
alarm(update_interval);
length = fread(buf, 1, size, fp);
pclose(fp); pclose(fp);
alarm(0);
buf[length] = '\0'; buf[length] = '\0';
if (length > 0 && buf[length - 1] == '\n') { if (length > 0 && buf[length - 1] == '\n') {
buf[length - 1] = '\0'; buf[length - 1] = '\0';
@ -9261,6 +9310,7 @@ void initialisation(int argc, char **argv) {
#endif #endif
if ( sigaction(SIGINT, &act, &oact) < 0 if ( sigaction(SIGINT, &act, &oact) < 0
|| sigaction(SIGALRM, &act, &oact) < 0
|| sigaction(SIGUSR1, &act, &oact) < 0 || sigaction(SIGUSR1, &act, &oact) < 0
|| sigaction(SIGHUP, &act, &oact) < 0 || sigaction(SIGHUP, &act, &oact) < 0
|| sigaction(SIGTERM, &act, &oact) < 0) { || sigaction(SIGTERM, &act, &oact) < 0) {
@ -9414,11 +9464,21 @@ int main(int argc, char **argv)
return 0; return 0;
} }
void alarm_handler(void) {
if(childpid > 0) {
kill(childpid, SIGTERM);
}
}
static void signal_handler(int sig) static void signal_handler(int sig)
{ {
/* signal handler is light as a feather, as it should be. /* signal handler is light as a feather, as it should be.
* we will poll g_signal_pending with each loop of conky * we will poll g_signal_pending with each loop of conky
* and do any signal processing there, NOT here. */ * and do any signal processing there, NOT here (except
g_signal_pending = sig; * SIGALRM because this is caused when conky is hanging) */
if(sig == SIGALRM) {
alarm_handler();
} else {
g_signal_pending = sig;
}
} }