Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / tools / perf / builtin-daemon.c
index 617feaf..61929f6 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/zalloc.h>
 #include <linux/string.h>
 #include <linux/limits.h>
-#include <linux/string.h>
 #include <string.h>
 #include <sys/file.h>
 #include <signal.h>
@@ -24,8 +23,6 @@
 #include <sys/signalfd.h>
 #include <sys/wait.h>
 #include <poll.h>
-#include <sys/stat.h>
-#include <time.h>
 #include "builtin.h"
 #include "perf.h"
 #include "debug.h"
@@ -161,7 +158,7 @@ static int session_config(struct daemon *daemon, const char *var, const char *va
        struct daemon_session *session;
        char name[100];
 
-       if (get_session_name(var, name, sizeof(name)))
+       if (get_session_name(var, name, sizeof(name) - 1))
                return -EINVAL;
 
        var = strchr(var, '.');
@@ -373,12 +370,12 @@ static int daemon_session__run(struct daemon_session *session,
        dup2(fd, 2);
        close(fd);
 
-       if (mkfifo(SESSION_CONTROL, O_RDWR) && errno != EEXIST) {
+       if (mkfifo(SESSION_CONTROL, 0600) && errno != EEXIST) {
                perror("failed: create control fifo");
                return -1;
        }
 
-       if (mkfifo(SESSION_ACK, O_RDWR) && errno != EEXIST) {
+       if (mkfifo(SESSION_ACK, 0600) && errno != EEXIST) {
                perror("failed: create ack fifo");
                return -1;
        }
@@ -402,35 +399,42 @@ static pid_t handle_signalfd(struct daemon *daemon)
        int status;
        pid_t pid;
 
+       /*
+        * Take signal fd data as pure signal notification and check all
+        * the sessions state. The reason is that multiple signals can get
+        * coalesced in kernel and we can receive only single signal even
+        * if multiple SIGCHLD were generated.
+        */
        err = read(daemon->signal_fd, &si, sizeof(struct signalfd_siginfo));
-       if (err != sizeof(struct signalfd_siginfo))
+       if (err != sizeof(struct signalfd_siginfo)) {
+               pr_err("failed to read signal fd\n");
                return -1;
+       }
 
        list_for_each_entry(session, &daemon->sessions, list) {
+               if (session->pid == -1)
+                       continue;
 
-               if (session->pid != (int) si.ssi_pid)
+               pid = waitpid(session->pid, &status, WNOHANG);
+               if (pid <= 0)
                        continue;
 
-               pid = waitpid(session->pid, &status, 0);
-               if (pid == session->pid) {
-                       if (WIFEXITED(status)) {
-                               pr_info("session '%s' exited, status=%d\n",
-                                       session->name, WEXITSTATUS(status));
-                       } else if (WIFSIGNALED(status)) {
-                               pr_info("session '%s' killed (signal %d)\n",
-                                       session->name, WTERMSIG(status));
-                       } else if (WIFSTOPPED(status)) {
-                               pr_info("session '%s' stopped (signal %d)\n",
-                                       session->name, WSTOPSIG(status));
-                       } else {
-                               pr_info("session '%s' Unexpected status (0x%x)\n",
-                                       session->name, status);
-                       }
+               if (WIFEXITED(status)) {
+                       pr_info("session '%s' exited, status=%d\n",
+                               session->name, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status)) {
+                       pr_info("session '%s' killed (signal %d)\n",
+                               session->name, WTERMSIG(status));
+               } else if (WIFSTOPPED(status)) {
+                       pr_info("session '%s' stopped (signal %d)\n",
+                               session->name, WSTOPSIG(status));
+               } else {
+                       pr_info("session '%s' Unexpected status (0x%x)\n",
+                               session->name, status);
                }
 
                session->state = KILL;
                session->pid = -1;
-               return pid;
        }
 
        return 0;
@@ -443,7 +447,6 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
                .fd     = daemon->signal_fd,
                .events = POLLIN,
        };
-       pid_t wpid = 0, pid = session->pid;
        time_t start;
 
        start = time(NULL);
@@ -452,7 +455,7 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
                int err = poll(&pollfd, 1, 1000);
 
                if (err > 0) {
-                       wpid = handle_signalfd(daemon);
+                       handle_signalfd(daemon);
                } else if (err < 0) {
                        perror("failed: poll\n");
                        return -1;
@@ -460,7 +463,7 @@ static int daemon_session__wait(struct daemon_session *session, struct daemon *d
 
                if (start + secs < time(NULL))
                        return -1;
-       } while (wpid != pid);
+       } while (session->pid != -1);
 
        return 0;
 }
@@ -902,7 +905,9 @@ static void daemon_session__kill(struct daemon_session *session,
                        daemon_session__signal(session, SIGKILL);
                        break;
                default:
-                       break;
+                       pr_err("failed to wait for session %s\n",
+                              session->name);
+                       return;
                }
                how++;
 
@@ -955,7 +960,8 @@ static void daemon__kill(struct daemon *daemon)
                        daemon__signal(daemon, SIGKILL);
                        break;
                default:
-                       break;
+                       pr_err("failed to wait for sessions\n");
+                       return;
                }
                how++;
 
@@ -1344,7 +1350,7 @@ out:
                close(sock_fd);
        if (conf_fd != -1)
                close(conf_fd);
-       if (conf_fd != -1)
+       if (signal_fd != -1)
                close(signal_fd);
 
        pr_info("daemon exited\n");