|
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include <fcntl.h> |
|
8 #include "UnixFdWatcher.h" |
|
9 |
|
10 #ifdef CHROMIUM_LOG |
|
11 #undef CHROMIUM_LOG |
|
12 #endif |
|
13 |
|
14 #if defined(MOZ_WIDGET_GONK) |
|
15 #include <android/log.h> |
|
16 #define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args); |
|
17 #else |
|
18 #include <stdio.h> |
|
19 #define IODEBUG true |
|
20 #define CHROMIUM_LOG(args...) if (IODEBUG) printf(args); |
|
21 #endif |
|
22 |
|
23 namespace mozilla { |
|
24 namespace ipc { |
|
25 |
|
26 UnixFdWatcher::~UnixFdWatcher() |
|
27 { |
|
28 NS_WARN_IF(IsOpen()); /* mFd should have been closed already */ |
|
29 } |
|
30 |
|
31 void |
|
32 UnixFdWatcher::Close() |
|
33 { |
|
34 MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); |
|
35 |
|
36 if (NS_WARN_IF(!IsOpen())) { |
|
37 /* mFd should have been open */ |
|
38 return; |
|
39 } |
|
40 OnClose(); |
|
41 RemoveWatchers(READ_WATCHER|WRITE_WATCHER); |
|
42 mFd.dispose(); |
|
43 } |
|
44 |
|
45 void |
|
46 UnixFdWatcher::AddWatchers(unsigned long aWatchers, bool aPersistent) |
|
47 { |
|
48 MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); |
|
49 MOZ_ASSERT(IsOpen()); |
|
50 |
|
51 // Before we add a watcher, we need to remove it! Removing is always |
|
52 // safe, but adding the same watcher twice can lead to endless loops |
|
53 // inside libevent. |
|
54 RemoveWatchers(aWatchers); |
|
55 |
|
56 if (aWatchers & READ_WATCHER) { |
|
57 MessageLoopForIO::current()->WatchFileDescriptor( |
|
58 mFd, |
|
59 aPersistent, |
|
60 MessageLoopForIO::WATCH_READ, |
|
61 &mReadWatcher, |
|
62 this); |
|
63 } |
|
64 if (aWatchers & WRITE_WATCHER) { |
|
65 MessageLoopForIO::current()->WatchFileDescriptor( |
|
66 mFd, |
|
67 aPersistent, |
|
68 MessageLoopForIO::WATCH_WRITE, |
|
69 &mWriteWatcher, |
|
70 this); |
|
71 } |
|
72 } |
|
73 |
|
74 void |
|
75 UnixFdWatcher::RemoveWatchers(unsigned long aWatchers) |
|
76 { |
|
77 MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); |
|
78 MOZ_ASSERT(IsOpen()); |
|
79 |
|
80 if (aWatchers & READ_WATCHER) { |
|
81 mReadWatcher.StopWatchingFileDescriptor(); |
|
82 } |
|
83 if (aWatchers & WRITE_WATCHER) { |
|
84 mWriteWatcher.StopWatchingFileDescriptor(); |
|
85 } |
|
86 } |
|
87 |
|
88 void |
|
89 UnixFdWatcher::OnError(const char* aFunction, int aErrno) |
|
90 { |
|
91 MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); |
|
92 |
|
93 CHROMIUM_LOG("%s failed with error %d (%s)", |
|
94 aFunction, aErrno, strerror(aErrno)); |
|
95 } |
|
96 |
|
97 UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop) |
|
98 : mIOLoop(aIOLoop) |
|
99 { |
|
100 MOZ_ASSERT(mIOLoop); |
|
101 } |
|
102 |
|
103 UnixFdWatcher::UnixFdWatcher(MessageLoop* aIOLoop, int aFd) |
|
104 : mIOLoop(aIOLoop) |
|
105 , mFd(aFd) |
|
106 { |
|
107 MOZ_ASSERT(mIOLoop); |
|
108 } |
|
109 |
|
110 void |
|
111 UnixFdWatcher::SetFd(int aFd) |
|
112 { |
|
113 MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop); |
|
114 MOZ_ASSERT(!IsOpen()); |
|
115 MOZ_ASSERT(FdIsNonBlocking(aFd)); |
|
116 |
|
117 mFd = aFd; |
|
118 } |
|
119 |
|
120 bool |
|
121 UnixFdWatcher::FdIsNonBlocking(int aFd) |
|
122 { |
|
123 int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL)); |
|
124 return (flags > 0) && (flags & O_NONBLOCK); |
|
125 } |
|
126 |
|
127 } |
|
128 } |