Bug 1008091 - send network change events on FxOS and Linux, r=sworkman
authorDaniel Stenberg <daniel@haxx.se>
Thu, 15 Jan 2015 00:22:00 +0100
changeset 238449 9ac55618810884e6982990ea4a050c5747144d12
parent 238448 d67c0b04dff2e1dd3a22425b5dc1fe10d2df7afa
child 238450 62002d8c930f78e77bfdb9aa5350d7df473c565c
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-esr52@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssworkman
bugs1008091
milestone38.0a1
Bug 1008091 - send network change events on FxOS and Linux, r=sworkman
netwerk/build/moz.build
netwerk/build/nsNetModule.cpp
netwerk/system/linux/moz.build
netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
netwerk/system/linux/nsNotifyAddrListener_Linux.h
netwerk/system/moz.build
xpcom/glue/FileUtils.h
--- a/netwerk/build/moz.build
+++ b/netwerk/build/moz.build
@@ -53,16 +53,21 @@ if CONFIG['MOZ_ENABLE_QTNETWORK']:
         '../system/qt',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     LOCAL_INCLUDES += [
         '../system/android',
     ]
 
+elif CONFIG['OS_ARCH'] == 'Linux':
+    LOCAL_INCLUDES += [
+        '../system/linux',
+    ]
+
 if CONFIG['NECKO_COOKIES']:
     LOCAL_INCLUDES += [
         '../cookie',
     ]
 
 if CONFIG['NECKO_WIFI']:
     LOCAL_INCLUDES += [
         '../wifi',
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -371,16 +371,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNo
 #include "nsNetworkLinkService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetworkLinkService, Init)
 #elif defined(MOZ_ENABLE_QTNETWORK)
 #include "nsQtNetworkLinkService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsQtNetworkLinkService, Init)
 #elif defined(MOZ_WIDGET_ANDROID)
 #include "nsAndroidNetworkLinkService.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidNetworkLinkService)
+#elif defined(XP_LINUX)
+#include "nsNotifyAddrListener_Linux.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNotifyAddrListener, Init)
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef NECKO_PROTOCOL_ftp
 #include "nsFTPDirListingConv.h"
 nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
 #endif
@@ -786,16 +789,18 @@ NS_DEFINE_NAMED_CID(NS_RTSPPROTOCOLHANDL
 #if defined(XP_WIN)
 NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
 #elif defined(MOZ_WIDGET_COCOA)
 NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
 #elif defined(MOZ_ENABLE_QTNETWORK)
 NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
 #elif defined(MOZ_WIDGET_ANDROID)
 NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
+#elif defined(XP_LINUX)
+NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID);
 NS_DEFINE_NAMED_CID(NS_REDIRECTCHANNELREGISTRAR_CID);
 NS_DEFINE_NAMED_CID(NS_CACHE_STORAGE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_NETWORKPREDICTOR_CID);
 
 static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
     { &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor },
@@ -930,16 +935,18 @@ static const mozilla::Module::CIDEntry k
 #if defined(XP_WIN)
     { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNotifyAddrListenerConstructor },
 #elif defined(MOZ_WIDGET_COCOA)
     { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNetworkLinkServiceConstructor },
 #elif defined(MOZ_ENABLE_QTNETWORK)
     { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsQtNetworkLinkServiceConstructor },
 #elif defined(MOZ_WIDGET_ANDROID)
     { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsAndroidNetworkLinkServiceConstructor },
+#elif defined(XP_LINUX)
+    { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNotifyAddrListenerConstructor },
 #endif
     { &kNS_SERIALIZATION_HELPER_CID, false, nullptr, nsSerializationHelperConstructor },
     { &kNS_REDIRECTCHANNELREGISTRAR_CID, false, nullptr, RedirectChannelRegistrarConstructor },
     { &kNS_CACHE_STORAGE_SERVICE_CID, false, nullptr, CacheStorageServiceConstructor },
     { &kNS_NETWORKPREDICTOR_CID, false, nullptr, mozilla::net::Predictor::Create },
     { nullptr }
 };
 
@@ -1077,16 +1084,18 @@ static const mozilla::Module::ContractID
 #if defined(XP_WIN)
     { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID },
 #elif defined(MOZ_WIDGET_COCOA)
     { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID },
 #elif defined(MOZ_ENABLE_QTNETWORK)
     { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID },
 #elif defined(MOZ_WIDGET_ANDROID)
     { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID },
+#elif defined(XP_LINUX)
+    { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID },
 #endif
     { NS_SERIALIZATION_HELPER_CONTRACTID, &kNS_SERIALIZATION_HELPER_CID },
     { NS_REDIRECTCHANNELREGISTRAR_CONTRACTID, &kNS_REDIRECTCHANNELREGISTRAR_CID },
     { NS_CACHE_STORAGE_SERVICE_CONTRACTID, &kNS_CACHE_STORAGE_SERVICE_CID },
     { NS_CACHE_STORAGE_SERVICE_CONTRACTID2, &kNS_CACHE_STORAGE_SERVICE_CID },
     { NS_NETWORKPREDICTOR_CONTRACTID, &kNS_NETWORKPREDICTOR_CID },
     { nullptr }
 };
new file mode 100644
--- /dev/null
+++ b/netwerk/system/linux/moz.build
@@ -0,0 +1,14 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+if CONFIG['OS_ARCH'] == 'Linux':
+    SOURCES += [
+        'nsNotifyAddrListener_Linux.cpp',
+    ]
+
+FAIL_ON_WARNINGS = True
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set et sw=4 ts=4: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+
+#include "nsThreadUtils.h"
+#include "nsIObserverService.h"
+#include "nsServiceManagerUtils.h"
+#include "nsNotifyAddrListener_Linux.h"
+#include "nsString.h"
+#include "nsAutoPtr.h"
+#include "prlog.h"
+
+#include "mozilla/Services.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/FileUtils.h"
+
+#ifdef MOZ_NUWA_PROCESS
+#include "ipc/Nuwa.h"
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+#include <cutils/properties.h>
+#endif
+
+/* a shorter name that better explains what it does */
+#define EINTR_RETRY(x) MOZ_TEMP_FAILURE_RETRY(x)
+
+using namespace mozilla;
+
+#if defined(PR_LOGGING)
+static PRLogModuleInfo *gNotifyAddrLog = nullptr;
+#define LOG(args) PR_LOG(gNotifyAddrLog, PR_LOG_DEBUG, args)
+#else
+#define LOG(args)
+#endif
+
+#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed"
+
+NS_IMPL_ISUPPORTS(nsNotifyAddrListener,
+                  nsINetworkLinkService,
+                  nsIRunnable,
+                  nsIObserver)
+
+nsNotifyAddrListener::nsNotifyAddrListener()
+    : mLinkUp(true)  // assume true by default
+    , mStatusKnown(false)
+    , mAllowChangedEvent(true)
+    , mChildThreadShutdown(false)
+{
+    mShutdownPipe[0] = -1;
+    mShutdownPipe[1] = -1;
+}
+
+nsNotifyAddrListener::~nsNotifyAddrListener()
+{
+    MOZ_ASSERT(!mThread, "nsNotifyAddrListener thread shutdown failed");
+
+    if (mShutdownPipe[0] != -1) {
+        EINTR_RETRY(close(mShutdownPipe[0]));
+    }
+    if (mShutdownPipe[1] != -1) {
+        EINTR_RETRY(close(mShutdownPipe[1]));
+    }
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::GetIsLinkUp(bool *aIsUp)
+{
+    // XXX This function has not yet been implemented for this platform
+    *aIsUp = mLinkUp;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::GetLinkStatusKnown(bool *aIsUp)
+{
+    // XXX This function has not yet been implemented for this platform
+    *aIsUp = mStatusKnown;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::GetLinkType(uint32_t *aLinkType)
+{
+  NS_ENSURE_ARG_POINTER(aLinkType);
+
+  // XXX This function has not yet been implemented for this platform
+  *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN;
+  return NS_OK;
+}
+
+void nsNotifyAddrListener::OnNetlinkMessage(int aNetlinkSocket)
+{
+    struct  nlmsghdr *nlh;
+    struct  rtmsg *route_entry;
+
+    // The buffer size below, (4095) was chosen partly based on testing and
+    // partly on existing sample source code using this size. It needs to be
+    // large enough to hold the netlink messages from the kernel.
+    char buffer[4095];
+
+    // Receiving netlink socket data
+    ssize_t rc = EINTR_RETRY(recv(aNetlinkSocket, buffer, sizeof(buffer), 0));
+    if (rc < 0) {
+        return;
+    }
+    size_t netlink_bytes = rc;
+
+    nlh = reinterpret_cast<struct nlmsghdr *>(buffer);
+
+    bool networkChange = false;
+
+    for (; NLMSG_OK(nlh, netlink_bytes);
+         nlh = NLMSG_NEXT(nlh, netlink_bytes)) {
+
+        if (NLMSG_DONE == nlh->nlmsg_type) {
+            break;
+        }
+
+        switch(nlh->nlmsg_type) {
+        case RTM_DELROUTE:
+        case RTM_NEWROUTE:
+            // Get the route data
+            route_entry = static_cast<struct rtmsg *>(NLMSG_DATA(nlh));
+
+            // We are just intrested in main routing table
+            if (route_entry->rtm_table != RT_TABLE_MAIN)
+                continue;
+
+            networkChange = true;
+            break;
+
+        case RTM_NEWADDR:
+            networkChange = true;
+            break;
+
+        default:
+            continue;
+        }
+    }
+
+    if (networkChange && mAllowChangedEvent) {
+        SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
+    }
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::Run()
+{
+    int netlinkSocket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if (netlinkSocket < 0) {
+        return NS_ERROR_FAILURE;
+    }
+
+    struct sockaddr_nl addr;
+    memset(&addr, 0, sizeof(addr));   // clear addr
+
+    addr.nl_family = AF_NETLINK;
+    addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR |
+        RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
+
+    if (bind(netlinkSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        // failure!
+        EINTR_RETRY(close(netlinkSocket));
+        return NS_ERROR_FAILURE;
+    }
+
+    // switch the socket into non-blocking
+    int flags = fcntl(netlinkSocket, F_GETFL, 0);
+    (void)fcntl(netlinkSocket, F_SETFL, flags | O_NONBLOCK);
+
+    struct pollfd fds[2];
+    fds[0].fd = mShutdownPipe[0];
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+
+    fds[1].fd = netlinkSocket;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    // when in b2g emulator, work around bug 1112499
+    int pollTimeout = -1;
+#ifdef MOZ_WIDGET_GONK
+    char propQemu[PROPERTY_VALUE_MAX];
+    property_get("ro.kernel.qemu", propQemu, "");
+    pollTimeout = !strncmp(propQemu, "1", 1) ? 100 : -1;
+#endif
+
+    nsresult rv = NS_OK;
+    bool shutdown = false;
+    while (!shutdown) {
+        int rc = EINTR_RETRY(poll(fds, 2, pollTimeout));
+
+        if (rc > 0) {
+            if (fds[0].revents & POLLIN) {
+                // shutdown, abort the loop!
+                LOG(("thread shutdown received, dying...\n"));
+                shutdown = true;
+            } else if (fds[1].revents & POLLIN) {
+                LOG(("netlink message received, handling it...\n"));
+                OnNetlinkMessage(netlinkSocket);
+            }
+        } else if (rc < 0) {
+            rv = NS_ERROR_FAILURE;
+            break;
+        }
+        if (mChildThreadShutdown) {
+            LOG(("thread shutdown via variable, dying...\n"));
+            shutdown = true;
+        }
+    }
+
+    EINTR_RETRY(close(netlinkSocket));
+
+    return rv;
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::Observe(nsISupports *subject,
+                              const char *topic,
+                              const char16_t *data)
+{
+    if (!strcmp("xpcom-shutdown-threads", topic)) {
+        Shutdown();
+    }
+
+    return NS_OK;
+}
+
+#ifdef MOZ_NUWA_PROCESS
+class NuwaMarkLinkMonitorThreadRunner : public nsRunnable
+{
+    NS_IMETHODIMP Run() MOZ_OVERRIDE
+    {
+        if (IsNuwaProcess()) {
+            NuwaMarkCurrentThread(nullptr, nullptr);
+        }
+        return NS_OK;
+    }
+};
+#endif
+
+nsresult
+nsNotifyAddrListener::Init(void)
+{
+#if defined(PR_LOGGING)
+    if (!gNotifyAddrLog)
+        gNotifyAddrLog = PR_NewLogModule("nsNotifyAddr");
+#endif
+
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+    if (!observerService)
+        return NS_ERROR_FAILURE;
+
+    nsresult rv = observerService->AddObserver(this, "xpcom-shutdown-threads",
+                                               false);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    Preferences::AddBoolVarCache(&mAllowChangedEvent,
+                                 NETWORK_NOTIFY_CHANGED_PREF, true);
+
+    rv = NS_NewNamedThread("Link Monitor", getter_AddRefs(mThread));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+#ifdef MOZ_NUWA_PROCESS
+    nsCOMPtr<nsIRunnable> runner = new NuwaMarkLinkMonitorThreadRunner();
+    mThread->Dispatch(runner, NS_DISPATCH_NORMAL);
+#endif
+
+    if (-1 == pipe(mShutdownPipe)) {
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
+nsresult
+nsNotifyAddrListener::Shutdown(void)
+{
+    // remove xpcom shutdown observer
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+    if (observerService)
+        observerService->RemoveObserver(this, "xpcom-shutdown-threads");
+
+    LOG(("write() to signal thread shutdown\n"));
+
+    // awake the thread to make it terminate
+    ssize_t rc = EINTR_RETRY(write(mShutdownPipe[1], "1", 1));
+    LOG(("write() returned %d, errno == %d\n", (int)rc, errno));
+
+    mChildThreadShutdown = true;
+
+    nsresult rv = mThread->Shutdown();
+
+    // Have to break the cycle here, otherwise nsNotifyAddrListener holds
+    // onto the thread and the thread holds onto the nsNotifyAddrListener
+    // via its mRunnable
+    mThread = nullptr;
+
+    return rv;
+}
+
+/* Sends the given event.  Assumes aEventID never goes out of scope (static
+ * strings are ideal).
+ */
+nsresult
+nsNotifyAddrListener::SendEvent(const char *aEventID)
+{
+    if (!aEventID)
+        return NS_ERROR_NULL_POINTER;
+
+    nsresult rv = NS_OK;
+    nsCOMPtr<nsIRunnable> event = new ChangeEvent(this, aEventID);
+    if (NS_FAILED(rv = NS_DispatchToMainThread(event)))
+        NS_WARNING("Failed to dispatch ChangeEvent");
+    return rv;
+}
+
+NS_IMETHODIMP
+nsNotifyAddrListener::ChangeEvent::Run()
+{
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+    if (observerService)
+        observerService->NotifyObservers(
+                mService, NS_NETWORK_LINK_TOPIC,
+                NS_ConvertASCIItoUTF16(mEventID).get());
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set et sw=4 ts=4: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef NSNOTIFYADDRLISTENER_LINUX_H_
+#define NSNOTIFYADDRLISTENER_LINUX_H_
+
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include "nsINetworkLinkService.h"
+#include "nsIRunnable.h"
+#include "nsIObserver.h"
+#include "nsThreadUtils.h"
+#include "nsCOMPtr.h"
+#include "mozilla/TimeStamp.h"
+
+class nsNotifyAddrListener : public nsINetworkLinkService,
+                             public nsIRunnable,
+                             public nsIObserver
+{
+    virtual ~nsNotifyAddrListener();
+
+public:
+    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_NSINETWORKLINKSERVICE
+    NS_DECL_NSIRUNNABLE
+    NS_DECL_NSIOBSERVER
+
+    nsNotifyAddrListener();
+    nsresult Init(void);
+
+private:
+    class ChangeEvent : public nsRunnable {
+    public:
+        NS_DECL_NSIRUNNABLE
+        ChangeEvent(nsINetworkLinkService *aService, const char *aEventID)
+            : mService(aService), mEventID(aEventID) {
+        }
+    private:
+        nsCOMPtr<nsINetworkLinkService> mService;
+        const char *mEventID;
+    };
+
+    // Called when xpcom-shutdown-threads is received.
+    nsresult Shutdown(void);
+
+    // Sends the network event.
+    nsresult SendEvent(const char *aEventID);
+
+    // Deals with incoming NETLINK messages.
+    void OnNetlinkMessage(int NetlinkSocket);
+
+    nsCOMPtr<nsIThread> mThread;
+
+    // The network is up.
+    bool mLinkUp;
+
+    // The network's up/down status is known.
+    bool mStatusKnown;
+
+    // A pipe to signal shutdown with.
+    int mShutdownPipe[2];
+
+    // Network changed events are enabled
+    bool mAllowChangedEvent;
+
+    // Flag to signal child thread kill with
+    bool mChildThreadShutdown;
+};
+
+#endif /* NSNOTIFYADDRLISTENER_LINUX_H_ */
--- a/netwerk/system/moz.build
+++ b/netwerk/system/moz.build
@@ -11,8 +11,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
     DIRS += ['mac']
 
 if CONFIG['MOZ_ENABLE_QTNETWORK']:
     DIRS += ['qt']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     DIRS += ['android']
 
+elif CONFIG['OS_ARCH'] == 'Linux':
+    DIRS += ['linux']
--- a/xpcom/glue/FileUtils.h
+++ b/xpcom/glue/FileUtils.h
@@ -156,33 +156,35 @@ void ReadAheadFile(pathstr_t aFilePath, 
  * (on Windows, file must be opened with FILE_FLAG_SEQUENTIAL_SCAN)
  * @param aOffset Offset into the file to begin preloading
  * @param aCount Number of bytes to preload (SIZE_MAX implies file size)
  */
 void ReadAhead(filedesc_t aFd, const size_t aOffset = 0,
                const size_t aCount = SIZE_MAX);
 
 
+#if defined(MOZ_WIDGET_GONK) || defined(XP_UNIX)
+#define MOZ_TEMP_FAILURE_RETRY(exp) (__extension__({ \
+  typeof (exp) _rc; \
+  do { \
+    _rc = (exp); \
+  } while (_rc == -1 && errno == EINTR); \
+  _rc; \
+}))
+#endif
+
 /* Define ReadSysFile() only on GONK to avoid unnecessary lubxul bloat.
 Also define it in debug builds, so that unit tests for it can be written
 and run in non-GONK builds. */
 #if (defined(MOZ_WIDGET_GONK) || defined(DEBUG)) && defined(XP_UNIX)
 
 #ifndef ReadSysFile_PRESENT
 #define ReadSysFile_PRESENT
 #endif /* ReadSysFile_PRESENT */
 
-#define MOZ_TEMP_FAILURE_RETRY(exp) (__extension__({ \
-  typeof (exp) _rc; \
-  do { \
-    _rc = (exp); \
-  } while (_rc == -1 && errno == EINTR); \
-  _rc; \
-}))
-
 /**
  * Read the contents of a file.
  * This function is intended for reading a single-lined text files from
  * /sys/. If the file ends with a newline ('\n') then it will be discarded.
  * The output buffer will always be '\0'-terminated on successful completion.
  * If aBufSize == 0, then this function will return true if the file exists
  * and is readable (it will not attempt to read anything from it).
  * On failure the contents of aBuf after this call will be undefined and the