diff --git a/src/util.c b/src/util.c index 2b21e33..59cbe61 100644 --- a/src/util.c +++ b/src/util.c @@ -253,14 +253,13 @@ alias_to_str(char *conf_choice) * \param cmd Command * \return child pid */ -int +pid_t spawn(const char *format, ...) { char *sh = NULL; char cmd[512]; va_list ap; - pid_t pid, ret; - int p[2]; + pid_t pid; size_t len; va_start(ap, format); @@ -276,48 +275,19 @@ spawn(const char *format, ...) if(!(sh = getenv("SHELL"))) sh = "/bin/sh"; - if (pipe(p) == -1) - { - warn("pipe"); - return -1; - } - if((pid = fork()) == 0) { - close(p[0]); - if((pid = fork()) == 0) - { - if(dpy) - close(ConnectionNumber(dpy)); - setsid(); - execl(sh, sh, "-c", cmd, (char*)NULL); - exit(EXIT_FAILURE); - } - - if (sizeof(pid_t) != write(p[1], &pid, sizeof(pid_t))) - warn("write"); - - close(p[1]); - exit(EXIT_SUCCESS); + if(dpy) + close(ConnectionNumber(dpy)); + setsid(); + if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1) + warn("execl(sh -c %s)", cmd); + exit(EXIT_FAILURE); } - else if (pid != -1) - { - close(p[1]); - if (sizeof(pid_t) != read(p[0], &ret, sizeof(pid_t))) - { - warn("read"); - ret = -1; - } - close(p[0]); - waitpid(pid, NULL, 0); - } - else - { + else if (pid == -1) warn("fork"); - ret = -1; - } - return ret; + return pid; } /** Swap two pointer. diff --git a/src/wmfs.c b/src/wmfs.c index 632c7e5..800efe3 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -32,6 +32,9 @@ #include "wmfs.h" +static volatile Bool exiting = False, sig_chld = False; +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + static void signal_handle(int); int @@ -141,27 +144,43 @@ quit(void) return; } -void * -thread_process(void *arg) +static void +wait_childs_and_status(void) { - XEvent ev; + int pid; - /* X event loop */ - if(arg) - { - while(!exiting && !XNextEvent(dpy, &ev)) - getevent(ev); + pthread_mutex_lock(&mtx); + if (sig_chld) { + while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) + if (pid == conf.status_pid) + conf.status_pid = -1; + sig_chld = False; } - /* Status checking loop with timing */ - else + pthread_mutex_unlock(&mtx); +} + +void * +thread_status(void *arg) +{ + (void)arg; + int left = conf.status_timing; + + pthread_detach(pthread_self()); + + do { - pthread_detach(pthread_self()); - do - { + wait_childs_and_status(); + + pthread_mutex_lock(&mtx); + if (conf.status_pid == -1) conf.status_pid = spawn(conf.status_path); - sleep(conf.status_timing); - } while (!exiting && conf.status_timing != 0); - } + pthread_mutex_unlock(&mtx); + + while ((left = sleep(left)) > 0); + left = conf.status_timing; + + } while (!exiting); + pthread_exit(NULL); } @@ -171,20 +190,23 @@ void mainloop(void) { XEvent ev; - pthread_t evloop, evstatus; - void *ret; + pthread_t th_status; - if(!estatus) - while(!exiting && !XNextEvent(dpy, &ev)) - getevent(ev); - else - { - pthread_create(&evloop, NULL, thread_process, "1"); - pthread_create(&evstatus, NULL, thread_process, NULL); - - (void)pthread_join(evloop, &ret); + if (estatus && conf.status_timing == 0) + conf.status_pid = spawn(conf.status_path); + else if (estatus && pthread_create(&th_status, NULL, thread_status, NULL) != 0) { + warnx("pthread_create"); + estatus = False; } + while (!exiting && !XNextEvent(dpy, &ev)) { + getevent(ev); + wait_childs_and_status(); + } + + if (estatus) + pthread_join(th_status, NULL); + return; } @@ -409,14 +431,9 @@ signal_handle(int sig) case SIGQUIT: case SIGTERM: exiting = True; - quit(); - exit(EXIT_SUCCESS); break; case SIGCHLD: - /* re-set signal handler and wait childs */ - if (signal(SIGCHLD, &signal_handle) == SIG_ERR) - warn("signal(%d)", SIGCHLD); - while (waitpid(-1, NULL, WNOHANG) > 0); + sig_chld = True; break; } @@ -435,7 +452,7 @@ main(int argc, char **argv) char *ol = "csgVS"; extern char *optarg; extern int optind; - int sigs[] = { SIGTERM, SIGQUIT, SIGCHLD }; + struct sigaction sa; argv_global = xstrdup(argv[0]); all_argv = argv; @@ -518,9 +535,12 @@ main(int argc, char **argv) errx(EXIT_FAILURE, "cannot open X server."); /* Set signal handler */ - for (i = sigs[0]; i < (int)LEN(sigs); i++) - if (signal(sigs[i], &signal_handle) == SIG_ERR) - warn("signal(%d)", sigs[i]); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = signal_handle; + sigemptyset(&sa.sa_mask); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGCHLD, &sa, NULL); /* Check if an other WM is already running; set the error handler */ XSetErrorHandler(errorhandler); diff --git a/src/wmfs.h b/src/wmfs.h index 108eacc..e8a9537 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -431,7 +431,7 @@ int selscreen; int prevselscreen; Conf conf; Key *keys; -Bool exiting, estatus; +Bool estatus; XRectangle *sgeo; XRectangle *spgeo; Cursor cursor[CurLast];