Don't futex_wait spin when setting properties. Wait for socket close.

Depends on init change I8dd685ea

Bug: 4185486
Change-Id: I5a2dbc3b7be1759212d4a3988d9033b9b947a1db
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index c40950f..3bdc9bf 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <stddef.h>
 #include <errno.h>
+#include <poll.h>
 
 #include <sys/mman.h>
 
@@ -156,15 +157,17 @@
 
 static int send_prop_msg(prop_msg *msg)
 {
+    struct pollfd pollfds[1];
     struct sockaddr_un addr;
     socklen_t alen;
     size_t namelen;
     int s;
     int r;
+    int result = -1;
 
     s = socket(AF_LOCAL, SOCK_STREAM, 0);
     if(s < 0) {
-        return -1;
+        return result;
     }
 
     memset(&addr, 0, sizeof(addr));
@@ -175,30 +178,37 @@
 
     if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) {
         close(s);
-        return -1;
+        return result;
     }
 
     r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
 
     if(r == sizeof(prop_msg)) {
-        r = 0;
-    } else {
-        r = -1;
+        // We successfully wrote to the property server but now we
+        // wait for the property server to finish its work.  It
+        // acknowledges its completion by closing the socket so we
+        // poll here (on nothing), waiting for the socket to close.
+        // If you 'adb shell setprop foo bar' you'll see the POLLHUP
+        // once the socket closes.  Out of paranoia we cap our poll
+        // at 250 ms.
+        pollfds[0].fd = s;
+        pollfds[0].events = 0;
+        r = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));
+        if (r == 1 && (pollfds[0].revents & POLLHUP) != 0) {
+            result = 0;
+        }
     }
 
     close(s);
-    return r;
+    return result;
 }
 
 int __system_property_set(const char *key, const char *value)
 {
-    unsigned old_serial;
-    volatile unsigned *serial;
-    prop_msg msg;
     int err;
-    prop_area *pa = __system_property_area__;
     int tries = 0;
     int update_seen = 0;
+    prop_msg msg;
 
     if(key == 0) return -1;
     if(value == 0) value = "";
@@ -210,54 +220,11 @@
     strlcpy(msg.name, key, sizeof msg.name);
     strlcpy(msg.value, value, sizeof msg.value);
 
-    /* Note the system properties serial number before we do our update. */
-    const prop_info *pi = __system_property_find(key);
-    if(pi != NULL) {
-        serial = &pi->serial;
-    } else {
-        serial = &pa->serial;
-    }
-    old_serial = *serial;
-
     err = send_prop_msg(&msg);
     if(err < 0) {
         return err;
     }
 
-    /**
-     * Wait for the shared memory page to be written back and be
-     * visible in our address space before returning to the caller
-     * who might reasonably expect subsequent reads to match what was
-     * just written.
-     *
-     * Sleep 5 ms after failed checks and only wait up to a 500 ms
-     * total, just in case the system property server fails to update
-     * for whatever reason.
-     */
-    do {
-        struct timespec timeout;
-        timeout.tv_sec = 0;
-        timeout.tv_nsec = 2500000;  // 2.5 ms
-
-        if(tries++ > 0) {
-            usleep(2500); // 2.5 ms
-        }
-        __futex_wait(serial, old_serial, &timeout);
-        if(pi != NULL) {
-            unsigned new_serial = *serial;
-            /* Waiting on a specific prop_info to be updated. */
-            if (old_serial != new_serial && !SERIAL_DIRTY(new_serial)) {
-                update_seen = 1;
-            }
-        } else {
-            /* Waiting for a prop_info to be created. */
-            const prop_info *new_pi = __system_property_find(key);
-            if(new_pi != NULL && !SERIAL_DIRTY(new_pi->serial)) {
-                update_seen = 1;
-            }
-        }
-    } while (!update_seen && tries < 100);
-
     return 0;
 }