michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include "UnixFdWatcher.h" michael@0: michael@0: #ifdef CHROMIUM_LOG michael@0: #undef CHROMIUM_LOG michael@0: #endif michael@0: michael@0: #if defined(MOZ_WIDGET_GONK) michael@0: #include michael@0: #define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); michael@0: #else michael@0: #include michael@0: #define IODEBUG true michael@0: #define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: michael@0: UnixFdWatcher::~UnixFdWatcher() michael@0: { michael@0: NS_WARN_IF(IsOpen()); /* mFd should have been closed already */ michael@0: } michael@0: michael@0: void michael@0: UnixFdWatcher::Close() michael@0: { michael@0: MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); michael@0: michael@0: if (NS_WARN_IF(!IsOpen())) { michael@0: /* mFd should have been open */ michael@0: return; michael@0: } michael@0: OnClose(); michael@0: RemoveWatchers(READ_WATCHER|WRITE_WATCHER); michael@0: mFd.dispose(); michael@0: } michael@0: michael@0: void michael@0: UnixFdWatcher::AddWatchers(unsigned long aWatchers, bool aPersistent) michael@0: { michael@0: MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); michael@0: MOZ_ASSERT(IsOpen()); michael@0: michael@0: // Before we add a watcher, we need to remove it! Removing is always michael@0: // safe, but adding the same watcher twice can lead to endless loops michael@0: // inside libevent. michael@0: RemoveWatchers(aWatchers); michael@0: michael@0: if (aWatchers & READ_WATCHER) { michael@0: MessageLoopForIO::current()->WatchFileDescriptor( michael@0: mFd, michael@0: aPersistent, michael@0: MessageLoopForIO::WATCH_READ, michael@0: &mReadWatcher, michael@0: this); michael@0: } michael@0: if (aWatchers & WRITE_WATCHER) { michael@0: MessageLoopForIO::current()->WatchFileDescriptor( michael@0: mFd, michael@0: aPersistent, michael@0: MessageLoopForIO::WATCH_WRITE, michael@0: &mWriteWatcher, michael@0: this); michael@0: } michael@0: } michael@0: michael@0: void michael@0: UnixFdWatcher::RemoveWatchers(unsigned long aWatchers) michael@0: { michael@0: MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); michael@0: MOZ_ASSERT(IsOpen()); michael@0: michael@0: if (aWatchers & READ_WATCHER) { michael@0: mReadWatcher.StopWatchingFileDescriptor(); michael@0: } michael@0: if (aWatchers & WRITE_WATCHER) { michael@0: mWriteWatcher.StopWatchingFileDescriptor(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: UnixFdWatcher::OnError(const char* aFunction, int aErrno) michael@0: { michael@0: MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); michael@0: michael@0: CHROMIUM_LOG("%s failed with error %d (%s)", michael@0: aFunction, aErrno, strerror(aErrno)); michael@0: } michael@0: michael@0: UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop) michael@0: : mIOLoop(aIOLoop) michael@0: { michael@0: MOZ_ASSERT(mIOLoop); michael@0: } michael@0: michael@0: UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop, int aFd) michael@0: : mIOLoop(aIOLoop) michael@0: , mFd(aFd) michael@0: { michael@0: MOZ_ASSERT(mIOLoop); michael@0: } michael@0: michael@0: void michael@0: UnixFdWatcher::SetFd(int aFd) michael@0: { michael@0: MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); michael@0: MOZ_ASSERT(!IsOpen()); michael@0: MOZ_ASSERT(FdIsNonBlocking(aFd)); michael@0: michael@0: mFd = aFd; michael@0: } michael@0: michael@0: bool michael@0: UnixFdWatcher::FdIsNonBlocking(int aFd) michael@0: { michael@0: int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); michael@0: return (flags > 0) && (flags & O_NONBLOCK); michael@0: } michael@0: michael@0: } michael@0: }