Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -149,10 +149,12 @@ 4B325EDD1605F3A0007836CA /* OFRunLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B325ED91605F3A0007836CA /* OFRunLoop.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B325EDE1605F3A0007836CA /* OFRunLoop.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B325EDA1605F3A0007836CA /* OFRunLoop.m */; }; 4B325EDF1605F3A0007836CA /* OFTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B325EDB1605F3A0007836CA /* OFTimer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B325EE01605F3A0007836CA /* OFTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B325EDC1605F3A0007836CA /* OFTimer.m */; }; 4B3379CF1979326A0088E97E /* threading.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3379CE1979326A0088E97E /* threading.m */; }; + 4B35C64E1ADAD30A003DB666 /* OFObserveFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B35C64C1ADAD30A003DB666 /* OFObserveFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B35C64F1ADAD30A003DB666 /* OFObserveFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B35C64D1ADAD30A003DB666 /* OFObserveFailedException.m */; }; 4B39844213D3A24600E6F825 /* OFSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844013D3A24600E6F825 /* OFSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B39844313D3A24600E6F825 /* OFSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39844113D3A24600E6F825 /* OFSet.m */; }; 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B39844513D3AFB400E6F825 /* OFMutableSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B39844813D3AFB400E6F825 /* OFMutableSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39844613D3AFB400E6F825 /* OFMutableSet.m */; }; 4B3B03EB19B3F70500F70C05 /* OFSHA256Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3B03E919B3F70500F70C05 /* OFSHA256Hash.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -656,10 +658,12 @@ 4B325ED91605F3A0007836CA /* OFRunLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRunLoop.h; path = src/OFRunLoop.h; sourceTree = ""; }; 4B325EDA1605F3A0007836CA /* OFRunLoop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRunLoop.m; path = src/OFRunLoop.m; sourceTree = ""; }; 4B325EDB1605F3A0007836CA /* OFTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFTimer.h; path = src/OFTimer.h; sourceTree = ""; }; 4B325EDC1605F3A0007836CA /* OFTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFTimer.m; path = src/OFTimer.m; sourceTree = ""; }; 4B3379CE1979326A0088E97E /* threading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = threading.m; path = src/threading.m; sourceTree = ""; }; + 4B35C64C1ADAD30A003DB666 /* OFObserveFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFObserveFailedException.h; path = src/exceptions/OFObserveFailedException.h; sourceTree = ""; }; + 4B35C64D1ADAD30A003DB666 /* OFObserveFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFObserveFailedException.m; path = src/exceptions/OFObserveFailedException.m; sourceTree = ""; }; 4B39844013D3A24600E6F825 /* OFSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSet.h; path = src/OFSet.h; sourceTree = ""; }; 4B39844113D3A24600E6F825 /* OFSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSet.m; path = src/OFSet.m; sourceTree = ""; }; 4B39844513D3AFB400E6F825 /* OFMutableSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMutableSet.h; path = src/OFMutableSet.h; sourceTree = ""; }; 4B39844613D3AFB400E6F825 /* OFMutableSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMutableSet.m; path = src/OFMutableSet.m; sourceTree = ""; }; 4B3B03E919B3F70500F70C05 /* OFSHA256Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSHA256Hash.h; path = src/OFSHA256Hash.h; sourceTree = ""; }; @@ -1095,10 +1099,12 @@ 4B7DD5841894358400990FD6 /* OFMoveItemFailedException.m */, 4B90B789133AD46700BD33CB /* OFNotConnectedException.h */, 4B90B78A133AD46700BD33CB /* OFNotConnectedException.m */, 4B17FF75133A2B18003E6DCD /* OFNotImplementedException.h */, 4B17FF76133A2B18003E6DCD /* OFNotImplementedException.m */, + 4B35C64C1ADAD30A003DB666 /* OFObserveFailedException.h */, + 4B35C64D1ADAD30A003DB666 /* OFObserveFailedException.m */, 4B55A107133AC05100B58A93 /* OFOpenItemFailedException.h */, 4B55A108133AC05100B58A93 /* OFOpenItemFailedException.m */, 4B17FF81133A2DFB003E6DCD /* OFOutOfMemoryException.h */, 4B17FF82133A2DFB003E6DCD /* OFOutOfMemoryException.m */, 4B17FF79133A2C14003E6DCD /* OFOutOfRangeException.h */, @@ -1745,10 +1751,11 @@ 4B17FFA1133A3335003E6DCD /* OFMalformedXMLException.h in Headers */, 4B17FF8F133A3036003E6DCD /* OFMemoryNotPartOfObjectException.h in Headers */, 4B7DD5851894358500990FD6 /* OFMoveItemFailedException.h in Headers */, 4B90B78F133AD46700BD33CB /* OFNotConnectedException.h in Headers */, 4B17FF77133A2B18003E6DCD /* OFNotImplementedException.h in Headers */, + 4B35C64E1ADAD30A003DB666 /* OFObserveFailedException.h in Headers */, 4B55A10A133AC05100B58A93 /* OFOpenItemFailedException.h in Headers */, 4B17FF83133A2DFB003E6DCD /* OFOutOfMemoryException.h in Headers */, 4B17FF7B133A2C15003E6DCD /* OFOutOfRangeException.h in Headers */, 4B55A112133AC24600B58A93 /* OFReadFailedException.h in Headers */, 4B55A114133AC24600B58A93 /* OFReadOrWriteFailedException.h in Headers */, @@ -2125,10 +2132,11 @@ 4B17FFA2133A3335003E6DCD /* OFMalformedXMLException.m in Sources */, 4B17FF90133A3036003E6DCD /* OFMemoryNotPartOfObjectException.m in Sources */, 4B7DD5861894358500990FD6 /* OFMoveItemFailedException.m in Sources */, 4B90B790133AD46700BD33CB /* OFNotConnectedException.m in Sources */, 4B17FF78133A2B18003E6DCD /* OFNotImplementedException.m in Sources */, + 4B35C64F1ADAD30A003DB666 /* OFObserveFailedException.m in Sources */, 4B55A10B133AC05100B58A93 /* OFOpenItemFailedException.m in Sources */, 4B17FF84133A2DFB003E6DCD /* OFOutOfMemoryException.m in Sources */, 4B17FF7C133A2C15003E6DCD /* OFOutOfRangeException.m in Sources */, 4B55A113133AC24600B58A93 /* OFReadFailedException.m in Sources */, 4B55A115133AC24600B58A93 /* OFReadOrWriteFailedException.m in Sources */, Index: src/OFKernelEventObserver_kqueue.m ================================================================== --- src/OFKernelEventObserver_kqueue.m +++ src/OFKernelEventObserver_kqueue.m @@ -18,10 +18,13 @@ #include #include #include +#include +#include + #include #include #include #import "OFKernelEventObserver.h" @@ -29,11 +32,11 @@ #import "OFKernelEventObserver_kqueue.h" #import "OFDataArray.h" #import "OFArray.h" #import "OFInitializationFailedException.h" -#import "OFOutOfMemoryException.h" +#import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" #define EVENTLIST_SIZE 64 @@ -123,11 +126,11 @@ - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { void *pool = objc_autoreleasePoolPush(); struct timespec timeout; struct kevent eventList[EVENTLIST_SIZE]; - int i, events, realEvents = 0; + int i, events, errNo, realEvents = 0; timeout.tv_sec = (time_t)timeInterval; timeout.tv_nsec = lrint((timeInterval - timeout.tv_sec) * 1000000000); /* @@ -144,15 +147,17 @@ objc_autoreleasePoolPop(pool); events = kevent(_kernelQueue, [_changeList items], (int)[_changeList count], eventList, EVENTLIST_SIZE, (timeInterval == -1 ? NULL : &timeout)); + errNo = errno; [_removedArray removeAllObjects]; if (events < 0) - return false; + return [OFObserveFailedException exceptionWithObserver: self + errNo: errNo]; [_changeList removeAllItems]; if (events == 0) return false; Index: src/OFKernelEventObserver_poll.m ================================================================== --- src/OFKernelEventObserver_poll.m +++ src/OFKernelEventObserver_poll.m @@ -16,19 +16,22 @@ #define __NO_EXT_QNX #include "config.h" +#include + #ifdef HAVE_POLL_H # include #endif #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_poll.h" #import "OFDataArray.h" +#import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" #ifdef __wii__ @@ -129,10 +132,11 @@ - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { void *pool = objc_autoreleasePoolPush(); struct pollfd *FDs; + int events; size_t i, nFDs, realEvents = 0; [self OF_processQueueAndStoreRemovedIn: nil]; if ([self OF_processCache]) { @@ -148,12 +152,18 @@ #ifdef OPEN_MAX if (nFDs > OPEN_MAX) @throw [OFOutOfRangeException exception]; #endif - if (poll(FDs, (nfds_t)nFDs, - (int)(timeInterval != -1 ? timeInterval * 1000 : -1)) < 1) + events = poll(FDs, (nfds_t)nFDs, + (int)(timeInterval != -1 ? timeInterval * 1000 : -1)); + + if (events < 0) + @throw [OFObserveFailedException exceptionWithObserver: self + errNo: errno]; + + if (events == 0) return false; for (i = 0; i < nFDs; i++) { pool = objc_autoreleasePoolPush(); Index: src/OFKernelEventObserver_select.m ================================================================== --- src/OFKernelEventObserver_select.m +++ src/OFKernelEventObserver_select.m @@ -16,20 +16,22 @@ #define __NO_EXT_QNX #include "config.h" -#include +#include #include +#include #include #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_select.h" #import "OFArray.h" +#import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" @implementation OFKernelEventObserver_select @@ -82,10 +84,11 @@ void *pool = objc_autoreleasePoolPush(); id const *objects; fd_set readFDs; fd_set writeFDs; struct timeval timeout; + int events; size_t i, count, realEvents = 0; [self OF_processQueueAndStoreRemovedIn: nil]; if ([self OF_processCache]) { @@ -114,12 +117,18 @@ #else timeout.tv_sec = (long)timeInterval; #endif timeout.tv_usec = (int)lrint((timeInterval - timeout.tv_sec) * 1000); - if (select((int)_maxFD + 1, &readFDs, &writeFDs, NULL, - (timeInterval != -1 ? &timeout : NULL)) < 1) + events = select((int)_maxFD + 1, &readFDs, &writeFDs, NULL, + (timeInterval != -1 ? &timeout : NULL)); + + if (events < 0) + @throw [OFObserveFailedException exceptionWithObserver: self + errNo: errno]; + + if (events == 0) return false; if (FD_ISSET(_cancelFD[0], &readFDs)) { char buffer; #ifndef _WIN32 Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -51,11 +51,12 @@ OFAlreadyConnectedException.m \ OFBindFailedException.m \ OFConnectionFailedException.m \ OFHTTPRequestFailedException.m \ OFListenFailedException.m \ - OFNotConnectedException.m + OFNotConnectedException.m \ + OFObserveFailedException.m SRCS_THREADS = OFConditionBroadcastFailedException.m \ OFConditionSignalFailedException.m \ OFConditionStillWaitingException.m \ OFConditionWaitFailedException.m \ OFThreadJoinFailedException.m \ ADDED src/exceptions/OFObserveFailedException.h Index: src/exceptions/OFObserveFailedException.h ================================================================== --- src/exceptions/OFObserveFailedException.h +++ src/exceptions/OFObserveFailedException.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFException.h" + +@class OFKernelEventObserver; + +/*! + * @class OFObserveFailedException \ + * OFObserveFailedException.h ObjFW/OFObserveFailedException.h + * + * @brief An exception indicating that observing failed. + */ +@interface OFObserveFailedException: OFException +{ + OFKernelEventObserver *_observer; + int _errNo; +} + +#ifdef OF_HAVE_PROPERTIES +@property (readonly, retain) OFKernelEventObserver *observer; +@property (readonly) int errNo; +#endif + +/*! + * @brief Creates a new, autoreleased observe failed exception. + * + * @param observer The observer which failed to observe + * @param errNo The errno of the error that occurred + * @return A new, autoreleased observe failed exception + */ ++ (instancetype)exceptionWithObserver: (OFKernelEventObserver*)observer + errNo: (int)errNo; + +/*! + * @brief Initializes an already allocated observe failed exception. + * + * @param observer The observer which failed to observe + * @param errNo The errno of the error that occurred + * @return An initialized observe failed exception + */ +- initWithObserver: (OFKernelEventObserver*)observer + errNo: (int)errNo; + +/*! + * @brief Returns the observer which failed to observe. + * + * @return The observer which failed to observe + */ +- (OFKernelEventObserver*)observer; + +/*! + * @brief Returns the errno of the error that occurred. + * + * @return The errno of the error that occurred + */ +- (int)errNo; +@end ADDED src/exceptions/OFObserveFailedException.m Index: src/exceptions/OFObserveFailedException.m ================================================================== --- src/exceptions/OFObserveFailedException.m +++ src/exceptions/OFObserveFailedException.m @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFObserveFailedException.h" +#import "OFString.h" +#import "OFKernelEventObserver.h" + +@implementation OFObserveFailedException ++ (instancetype)exceptionWithObserver: (OFKernelEventObserver*)observer + errNo: (int)errNo +{ + return [[[self alloc] initWithObserver: observer + errNo: errNo] autorelease]; +} + +- init +{ + OF_INVALID_INIT_METHOD +} + +- initWithObserver: (OFKernelEventObserver*)observer + errNo: (int)errNo +{ + self = [super init]; + + @try { + _observer = [observer retain]; + _errNo = errNo; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_observer release]; + + [super dealloc]; +} + +- (OFString*)description +{ + return [OFString stringWithFormat: + @"An observer of class %@ failed to observe: %@", + [_observer className], of_strerror(_errNo)]; +} + +- (OFKernelEventObserver*)observer +{ + OF_GETTER(_observer, true) +} + +- (int)errNo +{ + return _errNo; +} +@end