Source/PLCrashMachExceptionPortSet.m (50 lines of code) (raw):
/*
* Author: Landon Fuller <landonf@plausible.coop>
*
* Copyright (c) 2013 Plausible Labs Cooperative, Inc.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "PLCrashMacros.h"
#import "PLCrashMachExceptionPortSet.h"
#import "PLCrashFeatureConfig.h"
#if PLCRASH_FEATURE_MACH_EXCEPTIONS
/**
* @internal
*
* Represents an unordered set of PLCrashMachExceptionPortState instances.
*
* @par NSFastEnumeration
*
* This class conforms to NSFastEnumeration, which may be used to enumerate
* the managed PLCrashMachExceptionPortState instances.
*/
@implementation PLCrashMachExceptionPortSet
@synthesize asyncSafeRepresentation = _asyncSafeRepresentation;
@synthesize set = _state_set;
/**
* Initialize a new instance with the given @a set of PLCrashMachExceptionPortState instances.
*
* @param set A set of up to EXC_TYPES_COUNT PLCrashMachExceptionPortState instances.
*
* @warning If @a set contains more than EXC_TYPES_COUNT instances, an exception will be thrown.
*/
- (id) initWithSet: (NSSet *) set {
if ((self = [super init]) == nil)
return nil;
NSAssert([set count] <= EXC_TYPES_COUNT, @"Set size of %lu exceeds EXC_TYPES_COUNT (%lu)", (unsigned long)[set count], (unsigned long)EXC_TYPES_COUNT);
_state_set = set;
/* Initialize the async-safe C representation (using borrowed port references) */
plcrash_mach_exception_port_set_t port_set;
port_set.count = 0;
for (PLCrashMachExceptionPort *state in set) {
port_set.ports[port_set.count] = state.server_port;
port_set.masks[port_set.count] = state.mask;
port_set.behaviors[port_set.count] = state.behavior;
port_set.flavors[port_set.count] = state.flavor;
port_set.count++;
}
_asyncSafeRepresentation = port_set;
return self;
}
/**
* Initialize a new instance with the given async-safe C representation. The receiver will assume ownership of the associated mach ports, and
* will decrement their reference count upon deallocation.
*
* @param asyncSafeRepresentation An async-safe representation of the port state set (@sa plcrash_mach_exception_port_set_t)
*
* @warning If @a asyncSafeRepresentation contains more than EXC_TYPES_COUNT instances, an exception will be thrown.
*/
- (id) initWithAsyncSafeRepresentation: (plcrash_mach_exception_port_set_t) asyncSafeRepresentation {
if ((self = [super init]) == nil)
return nil;
plcrash_mach_exception_port_set_t *states = &asyncSafeRepresentation;
NSAssert(states->count <= EXC_TYPES_COUNT, @"Count of %lu exceeds EXC_TYPES_COUNT (%lu)", (unsigned long)states->count, (unsigned long)EXC_TYPES_COUNT);
kern_return_t kt;
NSMutableSet *stateResult = [NSMutableSet setWithCapacity: states->count];
for (mach_msg_type_number_t i = 0; i < states->count; i++) {
PLCrashMachExceptionPort *state = [[PLCrashMachExceptionPort alloc] initWithServerPort: states->ports[i]
mask: states->masks[i]
behavior: states->behaviors[i]
flavor: states->flavors[i]];
[stateResult addObject: state];
/* The state instance increments the refcount, and we acquire ownership of the caller's refcount */
if ((kt = mach_port_mod_refs(mach_task_self(), states->ports[i], MACH_PORT_RIGHT_SEND, -1)) != KERN_SUCCESS) {
PLCR_LOG("Unexpected error decrementing mach port reference: %d", kt);
}
}
_state_set = stateResult;
_asyncSafeRepresentation = asyncSafeRepresentation;
return self;
}
// from NSFastEnumeration protocol
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *) state objects: (id __unsafe_unretained _Nullable [_Nonnull]) stackbuf count: (NSUInteger) len {
return [_state_set countByEnumeratingWithState: state objects: stackbuf count: len];
}
@end
#endif