am 15b15c4b: am a14da5b1: am 499b45a3: Merge "libsysutils: Fix a file descriptor leak."

* commit '15b15c4b4acede0b999e6a7af9ce797c6a58a62a':
  libsysutils: Fix a file descriptor leak.
diff --git a/adb/sockets.c b/adb/sockets.c
index 43925e4..aa4d5fc 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -569,6 +569,32 @@
     return n;
 }
 
+/* skip_host_serial return the position in a string
+   skipping over the 'serial' parameter in the ADB protocol,
+   where parameter string may be a host:port string containing
+   the protocol delimiter (colon). */
+char *skip_host_serial(char *service) {
+    char *first_colon, *serial_end;
+
+    first_colon = strchr(service, ':');
+    if (!first_colon) {
+        /* No colon in service string. */
+        return NULL;
+    }
+    serial_end = first_colon;
+    if (isdigit(serial_end[1])) {
+        serial_end++;
+        while ((*serial_end) && isdigit(*serial_end)) {
+            serial_end++;
+        }
+        if ((*serial_end) != ':') {
+            // Something other than numbers was found, reset the end.
+            serial_end = first_colon;
+        }
+    }
+    return serial_end;
+}
+
 static int smart_socket_enqueue(asocket *s, apacket *p)
 {
     unsigned len;
@@ -624,8 +650,8 @@
         char* serial_end;
         service += strlen("host-serial:");
 
-        // serial number should follow "host:"
-        serial_end = strchr(service, ':');
+        // serial number should follow "host:" and could be a host:port string.
+        serial_end = skip_host_serial(service);
         if (serial_end) {
             *serial_end = 0; // terminate string
             serial = service;
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 7a3e781..685f147 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -37,7 +37,6 @@
 
 #include <private/android_filesystem_config.h>
 
-#include <byteswap.h>
 #include "debuggerd.h"
 #include "utility.h"
 
@@ -196,73 +195,6 @@
     if(sig) dump_fault_addr(tfd, tid, sig);
 }
 
-/* After randomization (ASLR), stack contents that point to randomized
- * code become uninterpretable (e.g. can't be resolved to line numbers).
- * Here, we bundle enough information so that stack analysis on the
- * server side can still be performed. This means we are leaking some
- * information about the device (its randomization base). We have to make
- * sure an attacker has no way of intercepting the tombstone.
- */
-
-typedef struct {
-    int32_t mmap_addr;
-    char tag[4]; /* 'P', 'R', 'E', ' ' */
-} prelink_info_t __attribute__((packed));
-
-static inline void set_prelink(long *prelink_addr,
-                               prelink_info_t *info)
-{
-    // We will assume the binary is little-endian, and test the
-    // host endianness here.
-    unsigned long test_endianness = 0xFF;
-
-    if (sizeof(prelink_info_t) == 8 && prelink_addr) {
-        if (*(unsigned char *)&test_endianness)
-            *prelink_addr = info->mmap_addr;
-        else
-            *prelink_addr = bswap_32(info->mmap_addr);
-    }
-}
-
-static int check_prelinked(const char *fname,
-                           long *prelink_addr)
-{
-    *prelink_addr = 0;
-    if (sizeof(prelink_info_t) != 8) return 0;
-
-    int fd = open(fname, O_RDONLY);
-    if (fd < 0) return 0;
-    off_t end = lseek(fd, 0, SEEK_END);
-    int nr = sizeof(prelink_info_t);
-
-    off_t sz = lseek(fd, -nr, SEEK_CUR);
-    if ((long)(end - sz) != (long)nr) return 0;
-    if (sz == (off_t)-1) return 0;
-
-    prelink_info_t info;
-    int num_read = read(fd, &info, nr);
-    if (num_read < 0) return 0;
-    if (num_read != sizeof(info)) return 0;
-
-    int prelinked = 0;
-    if (!strncmp(info.tag, "PRE ", 4)) {
-        set_prelink(prelink_addr, &info);
-        prelinked = 1;
-    }
-    if (close(fd) < 0) return 0;
-    return prelinked;
-}
-
-void dump_randomization_base(int tfd, bool at_fault) {
-    bool only_in_tombstone = !at_fault;
-    long prelink_addr;
-    check_prelinked("/system/lib/libc.so", &prelink_addr);
-    _LOG(tfd, only_in_tombstone,
-         "\nlibc base address: %08x\n", prelink_addr);
-}
-
-/* End of ASLR-related logic. */
-
 static void parse_elf_info(mapinfo *milist, pid_t pid)
 {
     mapinfo *mi;
@@ -353,7 +285,6 @@
         dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault);
     }
 
-    dump_randomization_base(tfd, at_fault);
     dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault);
 #elif __i386__
     /* If stack unwinder fails, use the default solution to dump the stack
diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h
index d99072a..c8ccc7e 100644
--- a/include/arch/darwin-x86/AndroidConfig.h
+++ b/include/arch/darwin-x86/AndroidConfig.h
@@ -305,12 +305,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h
index 9703c76..d828bd5 100644
--- a/include/arch/freebsd-x86/AndroidConfig.h
+++ b/include/arch/freebsd-x86/AndroidConfig.h
@@ -363,12 +363,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index 5138d90..83891cd 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -361,12 +361,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/linux-ppc/AndroidConfig.h b/include/arch/linux-ppc/AndroidConfig.h
index 60bddd6..00706dc 100644
--- a/include/arch/linux-ppc/AndroidConfig.h
+++ b/include/arch/linux-ppc/AndroidConfig.h
@@ -323,12 +323,4 @@
  */
 #define HAVE_PREAD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h
index 9303bb6..5562eae 100644
--- a/include/arch/linux-sh/AndroidConfig.h
+++ b/include/arch/linux-sh/AndroidConfig.h
@@ -366,12 +366,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h
index 6fd26ea..7dcaa98 100644
--- a/include/arch/linux-x86/AndroidConfig.h
+++ b/include/arch/linux-x86/AndroidConfig.h
@@ -333,12 +333,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h
index a6f7090..05dd220 100644
--- a/include/arch/target_linux-x86/AndroidConfig.h
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -350,12 +350,4 @@
  */
 #define HAVE_PRINTF_ZD 1
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * Most systems lack (and actually don't need) this flag.
- */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h
index 8a7e062..ad890b4 100644
--- a/include/arch/windows/AndroidConfig.h
+++ b/include/arch/windows/AndroidConfig.h
@@ -338,10 +338,4 @@
  */
 /* #define HAVE_PRINTF_ZD 1 */
 
-/*
- * We need to open binary files using O_BINARY on Windows.
- * We don't define it on Windows since it is part of the io headers.
- */
-/* #define O_BINARY 0 */
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
new file mode 100644
index 0000000..1b3b762
--- /dev/null
+++ b/include/cutils/bitops.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CUTILS_BITOPS_H
+#define __CUTILS_BITOPS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+static inline int popcount(unsigned int x)
+{
+    return __builtin_popcount(x);
+}
+
+static inline int popcountl(unsigned long x)
+{
+    return __builtin_popcountl(x);
+}
+
+static inline int popcountll(unsigned long long x)
+{
+    return __builtin_popcountll(x);
+}
+
+__END_DECLS
+
+#endif /* __CUTILS_BITOPS_H */
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index 2fcc331..d6bb7d5 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -19,6 +19,10 @@
     /* Peer group ID */
     gid_t mGid;
 
+    /* Reference count (starts at 1) */
+    pthread_mutex_t mRefCountMutex;
+    int mRefCount;
+
 public:
     SocketClient(int sock);
     virtual ~SocketClient() {}
@@ -34,6 +38,13 @@
 
     // Sending binary data:
     int sendData(const void *data, int len);
+
+    // Optional reference counting.  Reference count starts at 1.  If
+    // it's decremented to 0, it deletes itself.
+    // SocketListener creates a SocketClient (at refcount 1) and calls
+    // decRef() when it's done with the client.
+    void incRef();
+    bool decRef(); // returns true at 0 (but note: SocketClient already deleted)
 };
 
 typedef android::List<SocketClient *> SocketClientCollection;
diff --git a/init/devices.c b/init/devices.c
index 036b8f7..08d23e3 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -551,13 +551,19 @@
     return ret;
 }
 
+static int is_booting(void)
+{
+    return access("/dev/.booting", F_OK) == 0;
+}
+
 static void process_firmware_event(struct uevent *uevent)
 {
     char *root, *loading, *data, *file1 = NULL, *file2 = NULL;
     int l, loading_fd, data_fd, fw_fd;
+    int booting = is_booting();
 
-    log_event_print("firmware event { '%s', '%s' }\n",
-                    uevent->path, uevent->firmware);
+    INFO("firmware: loading '%s' for '%s'\n",
+         uevent->firmware, uevent->path);
 
     l = asprintf(&root, SYSFS_PREFIX"%s/", uevent->path);
     if (l == -1)
@@ -587,19 +593,29 @@
     if(data_fd < 0)
         goto loading_close_out;
 
+try_loading_again:
     fw_fd = open(file1, O_RDONLY);
     if(fw_fd < 0) {
         fw_fd = open(file2, O_RDONLY);
         if (fw_fd < 0) {
+            if (booting) {
+                    /* If we're not fully booted, we may be missing
+                     * filesystems needed for firmware, wait and retry.
+                     */
+                usleep(100000);
+                booting = is_booting();
+                goto try_loading_again;
+            }
+            INFO("firmware: could not open '%s' %d\n", uevent->firmware, errno);
             write(loading_fd, "-1", 2);
             goto data_close_out;
         }
     }
 
     if(!load_firmware(fw_fd, loading_fd, data_fd))
-        log_event_print("firmware copy success { '%s', '%s' }\n", root, uevent->firmware);
+        INFO("firmware: copy success { '%s', '%s' }\n", root, uevent->firmware);
     else
-        log_event_print("firmware copy failure { '%s', '%s' }\n", root, uevent->firmware);
+        INFO("firmware: copy failure { '%s', '%s' }\n", root, uevent->firmware);
 
     close(fw_fd);
 data_close_out:
@@ -620,7 +636,6 @@
 static void handle_firmware_event(struct uevent *uevent)
 {
     pid_t pid;
-    int status;
     int ret;
 
     if(strcmp(uevent->subsystem, "firmware"))
@@ -634,10 +649,6 @@
     if (!pid) {
         process_firmware_event(uevent);
         exit(EXIT_SUCCESS);
-    } else {
-        do {
-            ret = waitpid(pid, &status, 0);
-        } while (ret == -1 && errno == EINTR);
     }
 }
 
diff --git a/init/init.c b/init/init.c
index e13d4b1..1e31cf9 100755
--- a/init/init.c
+++ b/init/init.c
@@ -651,6 +651,10 @@
         ERROR("init startup failure\n");
         exit(1);
     }
+
+        /* signal that we hit this point */
+    unlink("/dev/.booting");
+
     return 0;
 }
 
@@ -708,6 +712,9 @@
     mount("proc", "/proc", "proc", 0, NULL);
     mount("sysfs", "/sys", "sysfs", 0, NULL);
 
+        /* indicate that booting is in progress to background fw loaders, etc */
+    close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
+
         /* We must have some place other than / to create the
          * device nodes for kmsg and null, otherwise we won't
          * be able to remount / read-only later on.
diff --git a/init/ueventd.c b/init/ueventd.c
index 0e97be7..1328d19 100644
--- a/init/ueventd.c
+++ b/init/ueventd.c
@@ -20,6 +20,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <signal.h>
+
 #include <private/android_filesystem_config.h>
 
 #include "ueventd.h"
@@ -37,6 +39,13 @@
     int nr;
     char tmp[32];
 
+        /* Prevent fire-and-forget children from becoming zombies.
+         * If we should need to wait() for some children in the future
+         * (as opposed to none right now), double-forking here instead
+         * of ignoring SIGCHLD may be the better solution.
+         */
+    signal(SIGCHLD, SIG_IGN);
+
     open_devnull_stdio();
     log_init();
 
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 030e677..af82a3c 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -31,6 +31,7 @@
 static const char DHCP_PROP_NAME_PREFIX[]  = "dhcp";
 static const int NAP_TIME = 200;   /* wait for 200ms at a time */
                                   /* when polling for property values */
+static const char DAEMON_NAME_RENEW[]  = "iprenew";
 static char errmsg[100];
 
 /*
@@ -138,6 +139,7 @@
                     uint32_t  *lease)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
+    char daemon_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
     char daemon_cmd[PROPERTY_VALUE_MAX * 2];
     const char *ctrl_prop = "ctl.start";
@@ -146,18 +148,23 @@
     snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
             DHCP_PROP_NAME_PREFIX,
             interface);
+
+    snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s",
+            DAEMON_PROP_NAME,
+            interface);
+
     /* Erase any previous setting of the dhcp result property */
     property_set(result_prop_name, "");
 
     /* Start the daemon and wait until it's ready */
     if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0'))
-        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:-h %s %s", DAEMON_NAME,
+        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-h %s %s", DAEMON_NAME, interface,
                  prop_value, interface);
     else
-        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:%s", DAEMON_NAME, interface);
+        snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME, interface, interface);
     memset(prop_value, '\0', PROPERTY_VALUE_MAX);
     property_set(ctrl_prop, daemon_cmd);
-    if (wait_for_property(DAEMON_PROP_NAME, desired_status, 10) < 0) {
+    if (wait_for_property(daemon_prop_name, desired_status, 10) < 0) {
         snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start");
         return -1;
     }
@@ -199,15 +206,24 @@
 int dhcp_stop(const char *interface)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
+    char daemon_prop_name[PROPERTY_KEY_MAX];
+    char daemon_cmd[PROPERTY_VALUE_MAX * 2];
     const char *ctrl_prop = "ctl.stop";
     const char *desired_status = "stopped";
 
     snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
             DHCP_PROP_NAME_PREFIX,
             interface);
+
+    snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s",
+            DAEMON_PROP_NAME,
+            interface);
+
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface);
+
     /* Stop the daemon and wait until it's reported to be stopped */
-    property_set(ctrl_prop, DAEMON_NAME);
-    if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) {
+    property_set(ctrl_prop, daemon_cmd);
+    if (wait_for_property(daemon_prop_name, desired_status, 5) < 0) {
         return -1;
     }
     property_set(result_prop_name, "failed");
@@ -219,12 +235,20 @@
  */
 int dhcp_release_lease(const char *interface)
 {
+    char daemon_prop_name[PROPERTY_KEY_MAX];
+    char daemon_cmd[PROPERTY_VALUE_MAX * 2];
     const char *ctrl_prop = "ctl.stop";
     const char *desired_status = "stopped";
 
+    snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s",
+            DAEMON_PROP_NAME,
+            interface);
+
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface);
+
     /* Stop the daemon and wait until it's reported to be stopped */
-    property_set(ctrl_prop, DAEMON_NAME);
-    if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) {
+    property_set(ctrl_prop, daemon_cmd);
+    if (wait_for_property(daemon_prop_name, desired_status, 5) < 0) {
         return -1;
     }
     return 0;
@@ -233,3 +257,53 @@
 char *dhcp_get_errmsg() {
     return errmsg;
 }
+
+/**
+ * Run WiMAX dhcp renew service.
+ * "wimax_renew" service shoud be included in init.rc.
+ */
+int dhcp_do_request_renew(const char *interface,
+                    in_addr_t *ipaddr,
+                    in_addr_t *gateway,
+                    in_addr_t *mask,
+                    in_addr_t *dns1,
+                    in_addr_t *dns2,
+                    in_addr_t *server,
+                    uint32_t  *lease)
+{
+    char result_prop_name[PROPERTY_KEY_MAX];
+    char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
+    char daemon_cmd[PROPERTY_VALUE_MAX * 2];
+    const char *ctrl_prop = "ctl.start";
+
+    snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
+            DHCP_PROP_NAME_PREFIX,
+            interface);
+
+    /* Erase any previous setting of the dhcp result property */
+    property_set(result_prop_name, "");
+
+    /* Start the renew daemon and wait until it's ready */
+    snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME_RENEW, interface, interface);
+    memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+    property_set(ctrl_prop, daemon_cmd);
+
+    /* Wait for the daemon to return a result */
+    if (wait_for_property(result_prop_name, NULL, 30) < 0) {
+        snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for DHCP Renew to finish");
+        return -1;
+    }
+
+    if (!property_get(result_prop_name, prop_value, NULL)) {
+        /* shouldn't ever happen, given the success of wait_for_property() */
+        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set");
+        return -1;
+    }
+    if (strcmp(prop_value, "ok") == 0) {
+        fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease);
+        return 0;
+    } else {
+        snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
+        return -1;
+    }
+}
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index a6aed26..90ca52e 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -15,8 +15,10 @@
         , mPid(-1)
         , mUid(-1)
         , mGid(-1)
+        , mRefCount(1)
 {
     pthread_mutex_init(&mWriteMutex, NULL);
+    pthread_mutex_init(&mRefCountMutex, NULL);
 
     struct ucred creds;
     socklen_t szCreds = sizeof(creds);
@@ -100,3 +102,25 @@
     pthread_mutex_unlock(&mWriteMutex);
     return 0;
 }
+
+void SocketClient::incRef() {
+    pthread_mutex_lock(&mRefCountMutex);
+    mRefCount++;
+    pthread_mutex_unlock(&mRefCountMutex);
+}
+
+bool SocketClient::decRef() {
+    bool deleteSelf = false;
+    pthread_mutex_lock(&mRefCountMutex);
+    mRefCount--;
+    if (mRefCount == 0) {
+        deleteSelf = true;
+    } else if (mRefCount < 0) {
+        SLOGE("SocketClient refcount went negative!");
+    }
+    pthread_mutex_unlock(&mRefCountMutex);
+    if (deleteSelf) {
+        delete this;
+    }
+    return deleteSelf;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 611d5fe..69ed79e 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -55,7 +55,7 @@
     }
     SocketClientCollection::iterator it;
     for (it = mClients->begin(); it != mClients->end();) {
-        delete (*it);
+        (*it)->decRef();
         it = mClients->erase(it);
     }
     delete mClients;
@@ -225,8 +225,11 @@
                 }
                 pthread_mutex_unlock(&mClientsLock);
                 /* Destroy the client */
-                close(c->getSocket());
-                delete c;
+                int socket = c->getSocket();
+                if (c->decRef()) {
+                    // Note: 'c' is deleted memory at this point.
+                    close(socket);
+                }
             }
         }
     }
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 7112ebf..bd00311 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -326,15 +326,9 @@
 
     fuse->all = &fuse->root;
 
+    memset(&fuse->root, 0, sizeof(fuse->root));
     fuse->root.nid = FUSE_ROOT_ID; /* 1 */
-    fuse->root.next = 0;
-    fuse->root.child = 0;
-    fuse->root.parent = 0;
-
-    fuse->root.all = 0;
     fuse->root.refcount = 2;
-
-    fuse->root.name = 0;
     rename_node(&fuse->root, path);
 }
 
diff --git a/toolbox/start.c b/toolbox/start.c
index 3bd9fbb..665a941 100644
--- a/toolbox/start.c
+++ b/toolbox/start.c
@@ -8,13 +8,14 @@
 int start_main(int argc, char *argv[])
 {
     char buf[1024];
+
     if(argc > 1) {
         property_set("ctl.start", argv[1]);
     } else {
-        /* default to "start zygote" "start runtime" */
+        /* defaults to starting the common services stopped by stop.c */
+        property_set("ctl.start", "surfaceflinger");
         property_set("ctl.start", "zygote");
-        property_set("ctl.start", "runtime");
     }
-    
+
     return 0;
 }
diff --git a/toolbox/stop.c b/toolbox/stop.c
index 05baffd..460f377 100644
--- a/toolbox/stop.c
+++ b/toolbox/stop.c
@@ -10,11 +10,10 @@
     if(argc > 1) {
         property_set("ctl.stop", argv[1]);
     } else{
-        /* default to "stop runtime" "stop zygote" */
-        property_set("ctl.stop", "runtime");
+        /* defaults to stopping the common services */
         property_set("ctl.stop", "zygote");
+        property_set("ctl.stop", "surfaceflinger");
     }
 
     return 0;
 }
-