ObjFW  Check-in [41ca862453]

Overview
Comment:OFKernelEventObserver_kqueue: Ignore EBADF

Removed file descriptors were returned in the event list with EBADF if
the file descriptor has been closed before removing them. Interpreting
that as a read event caused problems, as the file descriptor could not
be mapped to an object anymore, thus the entry in the event list is
skipped now if there was a EBADF error.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 41ca86245357a235b94306bd3ba73807dbce3a0f624b4eacb1c1e0785cdac1f9
User & Date: js on 2014-02-04 09:41:38
Other Links: manifest | tags
Context
2014-02-04
21:45
OFUDPSocket: Conform to OFCopying check-in: f836f5e65d user: js tags: trunk
09:41
OFKernelEventObserver_kqueue: Ignore EBADF check-in: 41ca862453 user: js tags: trunk
2014-02-03
19:11
OFKernelEventObserver: Fix a typo check-in: 678dd1cdc7 user: js tags: trunk
Changes

Modified src/OFKernelEventObserver.h from [2129421b71] to [5b1f9ce35e].

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
- (int)fileDescriptorForWriting;
@end

/*!
 * @brief A class that can observe multiple kernel events (e.g. streams being
 *	  ready to read) at once.
 *
 * @note Currently, Win32 can only observe TCP sockets!
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray *_readObjects;
	OFMutableArray *_writeObjects;
	__unsafe_unretained id *_FDToObject;
	size_t _maxFD;







|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
- (int)fileDescriptorForWriting;
@end

/*!
 * @brief A class that can observe multiple kernel events (e.g. streams being
 *	  ready to read) at once.
 *
 * @note Currently, Win32 can only observe TCP and UDP sockets!
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray *_readObjects;
	OFMutableArray *_writeObjects;
	__unsafe_unretained id *_FDToObject;
	size_t _maxFD;
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
- (void)observe;

/*!
 * @brief Observes all objects until an event happens on an object or the
 *	  timeout is reached.
 *
 * @param timeInterval The time to wait for an event, in seconds
 * @return A boolean whether events occurred during the timeinterval
 */
- (bool)observeForTimeInterval: (of_time_interval_t)timeInterval;

/*!
 * @brief Observes all objects until an event happens on an object or the
 *	  specified date is reached.
 *
 * @param date The until which to observe
 * @return A boolean whether events occurred until the specified date
 */
- (bool)observeUntilDate: (OFDate*)date;

/*!
 * @brief Cancels the currently blocking observe call.
 *
 * This is automatically done when a new object is added or removed by another







|








|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
- (void)observe;

/*!
 * @brief Observes all objects until an event happens on an object or the
 *	  timeout is reached.
 *
 * @param timeInterval The time to wait for an event, in seconds
 * @return A boolean whether events occurred before returning
 */
- (bool)observeForTimeInterval: (of_time_interval_t)timeInterval;

/*!
 * @brief Observes all objects until an event happens on an object or the
 *	  specified date is reached.
 *
 * @param date The until which to observe
 * @return A boolean whether events occurred before returning
 */
- (bool)observeUntilDate: (OFDate*)date;

/*!
 * @brief Cancels the currently blocking observe call.
 *
 * This is automatically done when a new object is added or removed by another

Modified src/OFKernelEventObserver.m from [5a67a78a49] to [8aa249806a].

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
			case QUEUE_ADD | QUEUE_WRITE:
				[_writeObjects addObject: object];

				[self OF_addFileDescriptorForWriting: fd];

				break;
			case QUEUE_REMOVE | QUEUE_READ:
				[_readObjects removeObjectIdenticalTo: object];

				[self OF_removeFileDescriptorForReading: fd];

				break;
			case QUEUE_REMOVE | QUEUE_WRITE:
				[_writeObjects removeObjectIdenticalTo: object];

				[self OF_removeFileDescriptorForWriting: fd];

				break;
			default:
				assert(0);
			}
		}








|

|



|

|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
			case QUEUE_ADD | QUEUE_WRITE:
				[_writeObjects addObject: object];

				[self OF_addFileDescriptorForWriting: fd];

				break;
			case QUEUE_REMOVE | QUEUE_READ:
				[self OF_removeFileDescriptorForReading: fd];

				[_readObjects removeObjectIdenticalTo: object];

				break;
			case QUEUE_REMOVE | QUEUE_WRITE:
				[self OF_removeFileDescriptorForWriting: fd];

				[_writeObjects removeObjectIdenticalTo: object];

				break;
			default:
				assert(0);
			}
		}

Modified src/OFKernelEventObserver_kqueue.m from [d4951ca160] to [79faaa634a].

148
149
150
151
152
153
154
























155
156
157
158
159
160
161
			continue;
		}

		realEvents++;

		pool = objc_autoreleasePoolPush();

























		switch (eventList[i].filter) {
		case EVFILT_READ:
			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForReading:)])
				[_delegate objectIsReadyForReading:
				    _FDToObject[eventList[i].ident]];
			break;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
			continue;
		}

		realEvents++;

		pool = objc_autoreleasePoolPush();

		/*
		 * If a file descriptor has been closed before it is removed
		 * from the kernel event observer, the file descriptor is not
		 * valid anymore and causes EBADF. As closing a file descriptor
		 * automatically removes it from the queue, there is nothing to
		 * do anymore.
		 *
		 * Ideally, a file descriptor should never be closed before it
		 * is removed from the kernel event observer, as in rare cases,
		 * it could result in removing the wrong object from the kernel
		 * event observer, for example if a file descriptor is closed,
		 * a new one created, added to the kernel event observer and
		 * then the old one removed, as the new one could now have the
		 * same file descriptor as the closed one had and thus the new
		 * one is removed.
		 *
		 * For other errors, call the callback like it was successful
		 * so that the read / write will generate an error and throw an
		 * exception.
		 */
		if ((eventList[i].flags & EV_ERROR) &&
		    eventList[i].data == EBADF)
			continue;

		switch (eventList[i].filter) {
		case EVFILT_READ:
			if ([_delegate respondsToSelector:
			    @selector(objectIsReadyForReading:)])
				[_delegate objectIsReadyForReading:
				    _FDToObject[eventList[i].ident]];
			break;