OSDN Git Service

daemon: do not leak resources
authorPeter Wu <lekensteyn@gmail.com>
Sun, 24 Nov 2013 00:01:21 +0000 (01:01 +0100)
committerPeter Wu <lekensteyn@gmail.com>
Sun, 24 Nov 2013 14:43:57 +0000 (15:43 +0100)
Before this patch, the client was responsible for removing FIFOs before
connecting. That left a whole bunch of FIFOs in the SuperUser /dev/...
directory. After This patch, the daemon removes FIFOs as soon as the client is
connected. (This is detected by making the daemon read from the control socket.)

This patch becomes unnecessary when file descriptors can be passed though
processes.

Superuser/jni/su/daemon.c

index e688149..55f10df 100644 (file)
@@ -242,10 +242,13 @@ static int daemon_accept(int fd) {
     }
     if (mkfifo(errfile, 0660) != 0) {
         PLOGE("mkfifo %s", errfile);
+        unlink(outfile);
         exit(-1);
     }
     if (mkfifo(infile, 0660) != 0) {
         PLOGE("mkfifo %s", infile);
+        unlink(errfile);
+        unlink(outfile);
         exit(-1);
     }
 
@@ -265,11 +268,15 @@ static int daemon_accept(int fd) {
         ptm = open("/dev/ptmx", O_RDWR);
         if (ptm <= 0) {
             PLOGE("ptm");
-            exit(-1);
+            goto unlink_n_exit;
         }
         if(grantpt(ptm) || unlockpt(ptm) || ((devname = (char*) ptsname(ptm)) == 0)) {
             PLOGE("ptm setup");
             close(ptm);
+unlink_n_exit:
+            unlink(infile);
+            unlink(errfile);
+            unlink(outfile);
             exit(-1);
         }
         LOGD("devname: %s", devname);
@@ -278,19 +285,25 @@ static int daemon_accept(int fd) {
     int outfd = open(outfile, O_WRONLY);
     if (outfd <= 0) {
         PLOGE("outfd daemon %s", outfile);
-        goto done;
+        goto unlink_n_exit;
     }
     int errfd = open(errfile, O_WRONLY);
     if (errfd <= 0) {
         PLOGE("errfd daemon %s", errfile);
-        goto done;
+        goto unlink_n_exit;
     }
     int infd = open(infile, O_RDONLY);
     if (infd <= 0) {
         PLOGE("infd daemon %s", infile);
-        goto done;
+        goto unlink_n_exit;
     }
 
+    // Wait for client to open pipes, then remove
+    read_int(fd);
+    unlink(infile);
+    unlink(errfile);
+    unlink(outfile);
+
     int code;
     // now fork and run main, watch for the child pid exit, and send that
     // across the control channel as the response.
@@ -361,7 +374,13 @@ static int daemon_accept(int fd) {
     int status;
     LOGD("waiting for child exit");
     if (waitpid(child, &status, 0) > 0) {
-        code = WEXITSTATUS(status);
+        if (WIFEXITED(status)) {
+            code = WEXITSTATUS(status);
+        } else if (WIFSIGNALED(status)) {
+            code = 128 + WTERMSIG(status);
+        } else {
+            code = -1;
+        }
     }
     else {
         code = -1;
@@ -448,9 +467,6 @@ int connect_daemon(int argc, char *argv[]) {
     sprintf(outfile, "%s/%d.stdout", REQUESTOR_DAEMON_PATH, getpid());
     sprintf(errfile, "%s/%d.stderr", REQUESTOR_DAEMON_PATH, getpid());
     sprintf(infile, "%s/%d.stdin", REQUESTOR_DAEMON_PATH, getpid());
-    unlink(errfile);
-    unlink(infile);
-    unlink(outfile);
 
     struct sockaddr_un sun;
 
@@ -511,11 +527,19 @@ int connect_daemon(int argc, char *argv[]) {
         exit(-1);
     }
 
+    // notify daemon that the pipes are open.
+    write_int(socketfd, 1);
+
     pump_async(STDIN_FILENO, infd);
     pump_async(errfd, STDERR_FILENO);
     pump(outfd, STDOUT_FILENO);
 
+    close(infd);
+    close(errfd);
+    close(outfd);
+
     int code = read_int(socketfd);
+    close(socketfd);
     LOGD("client exited %d", code);
     return code;
 }