static void
test_io_close(int with_timer, bool from_path)
{
	#define chunks 4
	#define READSIZE (512*1024)
	unsigned int i;
	const char *path = LARGE_FILE;
	int fd = open(path, O_RDONLY);
	if (fd == -1) {
		if (errno == ENOENT) {
			test_skip("Large file not found");
			return;
		}
		test_errno("open", errno, 0);
		test_stop();
	}
#ifdef F_GLOBAL_NOCACHE
	if (fcntl(fd, F_GLOBAL_NOCACHE, 1) == -1) {
		test_errno("fcntl F_GLOBAL_NOCACHE", errno, 0);
		test_stop();
	}
#endif
	struct stat sb;
	if (fstat(fd, &sb)) {
		test_errno("fstat", errno, 0);
		test_stop();
	}
	const size_t size = (size_t)sb.st_size / chunks;
	const int expected_error = with_timer? ECANCELED : 0;
	dispatch_source_t t = NULL;
	dispatch_group_t g = dispatch_group_create();
	dispatch_group_enter(g);
	void (^cleanup_handler)(int error) = ^(int error) {
		test_errno("create error", error, 0);
		dispatch_group_leave(g);
		close(fd);
	};
	dispatch_io_t io;
	if (!from_path) {
		io = dispatch_io_create(DISPATCH_IO_RANDOM, fd,
				dispatch_get_global_queue(0, 0), cleanup_handler);
	} else {
#if DISPATCHTEST_IO_PATH
		io = dispatch_io_create_with_path(DISPATCH_IO_RANDOM, path, O_RDONLY, 0,
				dispatch_get_global_queue(0, 0), cleanup_handler);
#endif
	}
	dispatch_io_set_high_water(io, READSIZE);
	if (with_timer == 1) {
		dispatch_io_set_low_water(io, READSIZE);
		dispatch_io_set_interval(io,  2 * NSEC_PER_SEC,
				DISPATCH_IO_STRICT_INTERVAL);
	} else if (with_timer == 2) {
		t = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
				dispatch_get_global_queue(0,0));
		dispatch_retain(io);
		dispatch_source_set_event_handler(t, ^{
			dispatch_io_close(io, DISPATCH_IO_STOP);
			dispatch_source_cancel(t);
		});
Example #2
0
 data (
     const data &other
 )
     : native( other.native )
 {
     XDISPATCH_ASSERT( native );
     dispatch_retain( native );
 }
Example #3
0
group::group (
    const group &other
)
    : object( other ),
      m_native( other.m_native )
{
    XDISPATCH_ASSERT( m_native );
    dispatch_retain( m_native );
}
Example #4
0
group::group (
    dispatch_group_t g
)
    : object(),
      m_native( g )
{
    XDISPATCH_ASSERT( m_native );
    dispatch_retain( m_native );
}
Example #5
0
queue::queue (
    const queue &other
)
    : m_native( other.m_native ),
      m_label( other.m_label )
{
    XDISPATCH_ASSERT( m_native );
    dispatch_retain( m_native );
}
Example #6
0
semaphore::semaphore (
    dispatch_semaphore_t sem
)
    : d( new data )
{
    XDISPATCH_ASSERT( sem );
    XDISPATCH_ASSERT( d.get() );
    d->native = sem;
    dispatch_retain( sem );
}
Example #7
0
int
OSMemoryNotificationTimedWait(OSMemoryNotificationRef note, OSMemoryNotificationLevel *level, const struct timeval *abstime)
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_retain(sema);
    
    dispatch_source_t memoryNotificationSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VM, 0, DISPATCH_VM_PRESSURE, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
    dispatch_source_set_event_handler(memoryNotificationSource, ^{
        dispatch_semaphore_signal(sema);
        dispatch_release(sema);
    });
Example #8
0
__XDISPATCH_USE_NAMESPACE

queue::queue (
    dispatch_queue_t q
)
    : m_native( q ),
      m_label( dispatch_queue_get_label( q ) )
{
    XDISPATCH_ASSERT( m_native );
    dispatch_retain( m_native );
}
Example #9
0
static VALUE 
rb_queue_init(VALUE self, SEL sel, VALUE name)
{
    StringValue(name);

    rb_queue_t *queue = RQueue(self);
    queue->should_release_queue = 1;
    queue->queue = dispatch_queue_create(RSTRING_PTR(name), NULL);
    assert(queue->queue != NULL);
    dispatch_retain(queue->queue);
    return self;
}
Example #10
0
queue::queue (
    dispatch_queue_t q
)
    : object(),
      d( new data )
{
    XDISPATCH_ASSERT( d.get() );
    dispatch_retain( q );
    d->native = q;
    XDISPATCH_ASSERT( d->native );
    d->label = std::string( dispatch_queue_get_label( q ) );
}
Example #11
0
group & group::operator = (
    const group &other
)
{
    if( *this != other )
    {
        object::operator = (
            other
        );

        m_native = other.m_native;
        XDISPATCH_ASSERT( m_native );
        dispatch_retain( m_native );
    }

    return *this;
}
Example #12
0
xdispatch::queue & queue::operator = (
    const queue &other
)
{
    if( *this != other )
    {
        object::operator = (
            other
        );

        m_native = other.m_native;
        XDISPATCH_ASSERT( m_native );
        dispatch_retain( m_native );
        m_label = other.m_label;
    }

    return *this;
}
Example #13
0
static Boolean
__SCPreferencesScheduleWithRunLoop(SCPreferencesRef	prefs,
				   CFRunLoopRef		runLoop,
				   CFStringRef		runLoopMode,
				   dispatch_queue_t	queue)
{
	Boolean			ok		= FALSE;
	SCPreferencesPrivateRef	prefsPrivate	= (SCPreferencesPrivateRef)prefs;

	pthread_mutex_lock(&prefsPrivate->lock);

	if ((prefsPrivate->dispatchQueue != NULL) ||		// if we are already scheduled on a dispatch queue
	    ((queue != NULL) && prefsPrivate->scheduled)) {	// if we are already scheduled on a CFRunLoop
		_SCErrorSet(kSCStatusInvalidArgument);
		goto done;
	}

	if (!prefsPrivate->scheduled) {
		CFMutableArrayRef       keys;

		if (prefsPrivate->session == NULL) {
			ok = __SCPreferencesAddSession(prefs);
			if (!ok) {
				goto done;
			}
		}

		CFRetain(prefs);	// hold a reference to the prefs

		keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		CFArrayAppendValue(keys, prefsPrivate->sessionKeyCommit);
		CFArrayAppendValue(keys, prefsPrivate->sessionKeyApply);
		(void) SCDynamicStoreSetNotificationKeys(prefsPrivate->session, keys, NULL);
		CFRelease(keys);

		if (runLoop != NULL) {
			prefsPrivate->rls = SCDynamicStoreCreateRunLoopSource(NULL, prefsPrivate->session, 0);
			prefsPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		}

		prefsPrivate->scheduled = TRUE;
	}

	if (queue != NULL) {
		ok = SCDynamicStoreSetDispatchQueue(prefsPrivate->session, queue);
		if (!ok) {
			prefsPrivate->scheduled = FALSE;
			(void) SCDynamicStoreSetNotificationKeys(prefsPrivate->session, NULL, NULL);
			CFRelease(prefs);
			goto done;
		}

		prefsPrivate->dispatchQueue = queue;
		dispatch_retain(prefsPrivate->dispatchQueue);
	} else {
		if (!_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) {
			/*
			 * if we do not already have notifications scheduled with
			 * this runLoop / runLoopMode
			 */
			CFRunLoopAddSource(runLoop, prefsPrivate->rls, runLoopMode);
		}

		_SC_schedule(prefs, runLoop, runLoopMode, prefsPrivate->rlList);
	}

	ok = TRUE;

    done :

	pthread_mutex_unlock(&prefsPrivate->lock);
	return ok;
}
Boolean
SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store, dispatch_queue_t queue)
{
	dispatch_group_t		drainGroup	= NULL;
	dispatch_queue_t		drainQueue	= NULL;
	dispatch_group_t		group		= NULL;
	mach_port_t			mp;
	Boolean				ok		= FALSE;
	dispatch_source_t		source;
	SCDynamicStorePrivateRef	storePrivate	= (SCDynamicStorePrivateRef)store;

	if (store == NULL) {
		// sorry, you must provide a session
		_SCErrorSet(kSCStatusNoStoreSession);
		return FALSE;
	}

	if (queue == NULL) {
		if (storePrivate->dispatchQueue == NULL) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}

		ok = TRUE;
		goto cleanup;
	}

	if (storePrivate->server == MACH_PORT_NULL) {
		// sorry, you must have an open session to play
		_SCErrorSet(kSCStatusNoStoreServer);
		return FALSE;
	}

	if ((storePrivate->dispatchQueue != NULL) || (storePrivate->rls != NULL)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if (storePrivate->notifyStatus != NotifierNotRegistered) {
		// sorry, you can only have one notification registered at once...
		_SCErrorSet(kSCStatusNotifierActive);
		return FALSE;
	}

	/*
	 * mark our using of the SCDynamicStore notifications, create and schedule
	 * the notification port (storePrivate->rlsNotifyPort), and a bunch of other
	 * "setup"
	 */
	storePrivate->notifyStatus = Using_NotifierInformViaDispatch;
	rlsSchedule((void*)store, NULL, NULL);
	if (storePrivate->rlsNotifyPort == NULL) {
		/* if we could not schedule the notification */
		_SCErrorSet(kSCStatusFailed);
		goto cleanup;
	}

	// retain the dispatch queue
	storePrivate->dispatchQueue = queue;
	dispatch_retain(storePrivate->dispatchQueue);

	//
	// We've taken a reference to the callers dispatch_queue and we
	// want to hold on to that reference until we've processed any/all
	// notifications.  To facilitate this we create a group, dispatch
	// any notification blocks to via that group, and when the caller
	// has told us to stop the notifications (unschedule) we wait for
	// the group to empty and use the group's finalizer to release
	// our reference to the SCDynamicStore.
	//
	group = dispatch_group_create();
	storePrivate->dispatchGroup = group;
	CFRetain(store);
	dispatch_set_context(storePrivate->dispatchGroup, (void *)store);
	dispatch_set_finalizer_f(storePrivate->dispatchGroup, (dispatch_function_t)CFRelease);

	// create a dispatch source for the mach notifications
	mp = CFMachPortGetPort(storePrivate->rlsNotifyPort);
	source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, queue);
	if (source == NULL) {
		SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStore dispatch_source_create() failed"));
		_SCErrorSet(kSCStatusFailed);
		goto cleanup;
	}

	dispatch_source_set_event_handler(source, ^{
		kern_return_t	kr;
		mach_msg_id_t	msgid;
		union {
			u_int8_t			buf[sizeof(mach_msg_empty_t) + MAX_TRAILER_SIZE];
			mach_msg_empty_rcv_t		msg;
			mach_no_senders_notification_t	no_senders;
		} notify_msg;

		kr = mach_msg(&notify_msg.msg.header,	// msg
			      MACH_RCV_MSG,		// options
			      0,			// send_size
			      sizeof(notify_msg),	// rcv_size
			      mp,			// rcv_name
			      MACH_MSG_TIMEOUT_NONE,	// timeout
			      MACH_PORT_NULL);		// notify
		if (kr != KERN_SUCCESS) {
			SCLog(TRUE, LOG_ERR,
			      CFSTR("SCDynamicStore notification handler, kr=0x%x"),
			      kr);
			return;
		}

		msgid = notify_msg.msg.header.msgh_id;

		CFRetain(store);
		dispatch_group_async(group, queue, ^{
			if (msgid == MACH_NOTIFY_NO_SENDERS) {
				// re-establish notification and inform the client
				(void)__SCDynamicStoreReconnectNotifications(store);
			}
			rlsPerform(storePrivate);
			CFRelease(store);
		});
	});
Example #15
0
__private_extern__
Boolean
__SCDynamicStoreReconnectNotifications(SCDynamicStoreRef store)
{
	dispatch_queue_t			dispatchQueue	= NULL;
	__SCDynamicStoreNotificationStatus	notifyStatus;
	Boolean					ok		= TRUE;
	CFArrayRef				rlList		= NULL;
	SCDynamicStorePrivateRef		storePrivate	= (SCDynamicStorePrivateRef)store;

	// save old SCDynamicStore [notification] state
	notifyStatus = storePrivate->notifyStatus;

	// before tearing down our [old] notifications, make sure we've
	// retained any information that will be lost when we cancel the
	// current no-longer-valid handler
	switch (notifyStatus) {
		case Using_NotifierInformViaRunLoop :
			if (storePrivate->rlList != NULL) {
				rlList = CFArrayCreateCopy(NULL, storePrivate->rlList);
			}
		case Using_NotifierInformViaDispatch :
			dispatchQueue = storePrivate->dispatchQueue;
			if (dispatchQueue != NULL) dispatch_retain(dispatchQueue);
			break;
		default :
			break;
	}

	// cancel [old] notifications
	if (!SCDynamicStoreNotifyCancel(store)) {
		// if we could not cancel / reconnect
		SCLog(TRUE, LOG_DEBUG,
		      CFSTR("__SCDynamicStoreReconnectNotifications: SCDynamicStoreNotifyCancel() failed: %s"),
		      SCErrorString(SCError()));
	}

	// set notification keys & patterns
	if ((storePrivate->keys != NULL) || (storePrivate->patterns)) {
		ok = SCDynamicStoreSetNotificationKeys(store,
						       storePrivate->keys,
						       storePrivate->patterns);
		if (!ok) {
			SCLog((SCError() != BOOTSTRAP_UNKNOWN_SERVICE),
			      LOG_ERR,
			      CFSTR("__SCDynamicStoreReconnectNotifications: SCDynamicStoreSetNotificationKeys() failed"));
			goto done;
		}
	}

	switch (notifyStatus) {
		case Using_NotifierInformViaRunLoop : {
			CFIndex			i;
			CFIndex			n;
			CFRunLoopSourceRef	rls;

			rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
			if (rls == NULL) {
				SCLog((SCError() != BOOTSTRAP_UNKNOWN_SERVICE),
				      LOG_ERR,
				      CFSTR("__SCDynamicStoreReconnectNotifications: SCDynamicStoreCreateRunLoopSource() failed"));
				ok = FALSE;
				break;
			}

			n = (rlList != NULL) ? CFArrayGetCount(rlList) : 0;
			for (i = 0; i < n; i += 3) {
				CFRunLoopRef	rl	= (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
				CFStringRef	rlMode	= (CFStringRef) CFArrayGetValueAtIndex(rlList, i+2);

				CFRunLoopAddSource(rl, rls, rlMode);
			}

			CFRelease(rls);
			break;
		}
		case Using_NotifierInformViaDispatch :
			ok = SCDynamicStoreSetDispatchQueue(store, dispatchQueue);
			if (!ok) {
				SCLog((SCError() != BOOTSTRAP_UNKNOWN_SERVICE),
				      LOG_ERR,
				      CFSTR("__SCDynamicStoreReconnectNotifications: SCDynamicStoreSetDispatchQueue() failed"));
				goto done;
			}
			break;

		default :
			_SCErrorSet(kSCStatusFailed);
			ok = FALSE;
			break;
	}

    done :

	// cleanup
	switch (notifyStatus) {
		case Using_NotifierInformViaRunLoop :
			if (rlList != NULL) CFRelease(rlList);
			break;
		case Using_NotifierInformViaDispatch :
			if (dispatchQueue != NULL) dispatch_release(dispatchQueue);
			break;
		default :
			break;
	}

	if (!ok) {
		SCLog(TRUE, LOG_ERR,
		      CFSTR("SCDynamicStore server %s, notification (%s) not restored"),
		      (SCError() == BOOTSTRAP_UNKNOWN_SERVICE) ? "shutdown" : "failed",
		      notifyType[notifyStatus]);
	}

	// inform the client
	pushDisconnect(store);

	return ok;
}
int
main(int argc, char** argv)
{
	struct hostent *he;
	int sockfd, clientfd;
	struct sockaddr_in addr1, addr2, server;
	socklen_t addr2len;
	socklen_t addr1len;
	pid_t clientid;

	const char *path = "/usr/share/dict/words";
	int read_fd, fd;

	if (argc == 2) {
		// Client
		dispatch_test_start(NULL);

		if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
			test_errno("Client-socket()", errno, 0);
			test_stop();
		}

		if ((he = gethostbyname("localhost")) == NULL) {
			fprintf(stderr, "Client-gethostbyname() failed\n");
			test_stop();
		}

		memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
		server.sin_family = AF_INET;
		server.sin_port = atoi(argv[1]);

		fprintf(stderr, "Client-connecting on port ... %d\n", server.sin_port);

		if (connect(sockfd, (struct sockaddr *)&server, sizeof(server))) {
			test_errno("client-connect()", errno, 0);
			test_stop();
		}

		// Read from the socket and compare the contents are what we expect

		fd = open(path, O_RDONLY);
		if (fd == -1) {
			test_errno("client-open", errno, 0);
			test_stop();
		}
#ifdef F_NOCACHE
		if (fcntl(fd, F_NOCACHE, 1)) {
			test_errno("client-fcntl F_NOCACHE", errno, 0);
			test_stop();
		}
#else
		// investigate what the impact of lack of file cache disabling has 
		// for this test
#endif
		struct stat sb;
		if (fstat(fd, &sb)) {
			test_errno("client-fstat", errno, 0);
			test_stop();
		}
		size_t size = sb.st_size;

		__block dispatch_data_t g_d1 = dispatch_data_empty;
		__block dispatch_data_t g_d2 = dispatch_data_empty;
		__block int g_error = 0;

		dispatch_group_t g = dispatch_group_create();
		dispatch_group_enter(g);
		dispatch_read(fd, size, dispatch_get_global_queue(0, 0),
				^(dispatch_data_t d1, int error) {
			test_errno("Client-dict-read error", error, 0);
			test_long("Client-dict-dispatch data size",
					dispatch_data_get_size(d1), size);
			dispatch_retain(d1);
			g_d1 = d1;
			dispatch_group_leave(g);
		});