diff options
Diffstat (limited to 'ipc/unixfd/UnixFdWatcher.cpp')
-rw-r--r-- | ipc/unixfd/UnixFdWatcher.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/ipc/unixfd/UnixFdWatcher.cpp b/ipc/unixfd/UnixFdWatcher.cpp new file mode 100644 index 000000000..41289a90b --- /dev/null +++ b/ipc/unixfd/UnixFdWatcher.cpp @@ -0,0 +1,128 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 <fcntl.h> +#include "UnixFdWatcher.h" + +#ifdef CHROMIUM_LOG +#undef CHROMIUM_LOG +#endif + +#if defined(MOZ_WIDGET_GONK) +#include <android/log.h> +#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); +#else +#include <stdio.h> +#define IODEBUG true +#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); +#endif + +namespace mozilla { +namespace ipc { + +UnixFdWatcher::~UnixFdWatcher() +{ + NS_WARNING_ASSERTION(!IsOpen(), "mFd should have been closed already"); +} + +void +UnixFdWatcher::Close() +{ + MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); + + if (NS_WARN_IF(!IsOpen())) { + /* mFd should have been open */ + return; + } + OnClose(); + RemoveWatchers(READ_WATCHER|WRITE_WATCHER); + mFd.dispose(); +} + +void +UnixFdWatcher::AddWatchers(unsigned long aWatchers, bool aPersistent) +{ + MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); + MOZ_ASSERT(IsOpen()); + + // Before we add a watcher, we need to remove it! Removing is always + // safe, but adding the same watcher twice can lead to endless loops + // inside libevent. + RemoveWatchers(aWatchers); + + if (aWatchers & READ_WATCHER) { + MessageLoopForIO::current()->WatchFileDescriptor( + mFd, + aPersistent, + MessageLoopForIO::WATCH_READ, + &mReadWatcher, + this); + } + if (aWatchers & WRITE_WATCHER) { + MessageLoopForIO::current()->WatchFileDescriptor( + mFd, + aPersistent, + MessageLoopForIO::WATCH_WRITE, + &mWriteWatcher, + this); + } +} + +void +UnixFdWatcher::RemoveWatchers(unsigned long aWatchers) +{ + MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); + MOZ_ASSERT(IsOpen()); + + if (aWatchers & READ_WATCHER) { + mReadWatcher.StopWatchingFileDescriptor(); + } + if (aWatchers & WRITE_WATCHER) { + mWriteWatcher.StopWatchingFileDescriptor(); + } +} + +void +UnixFdWatcher::OnError(const char* aFunction, int aErrno) +{ + MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); + + CHROMIUM_LOG("%s failed with error %d (%s)", + aFunction, aErrno, strerror(aErrno)); +} + +UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop) +: mIOLoop(aIOLoop) +{ + MOZ_ASSERT(mIOLoop); +} + +UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop, int aFd) +: mIOLoop(aIOLoop) +, mFd(aFd) +{ + MOZ_ASSERT(mIOLoop); +} + +void +UnixFdWatcher::SetFd(int aFd) +{ + MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); + MOZ_ASSERT(!IsOpen()); + MOZ_ASSERT(FdIsNonBlocking(aFd)); + + mFd = aFd; +} + +bool +UnixFdWatcher::FdIsNonBlocking(int aFd) +{ + int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); + return (flags > 0) && (flags & O_NONBLOCK); +} + +} +} |