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:
parent
4d37d021e1
commit
b963c2827f
70
src/conky.c
70
src/conky.c
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user