From 3014670f2f48bc435af758b6155efca0b3ad3bc3 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 10 May 2012 20:20:40 +0000 Subject: [PATCH] libdispatch-187.9.tar.gz --- src/io.c | 24 +++++++++++++----------- src/source.c | 11 ++++++++--- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/io.c b/src/io.c index b306054..d01c266 100644 --- a/src/io.c +++ b/src/io.c @@ -266,7 +266,7 @@ _dispatch_io_init(dispatch_io_t channel, dispatch_fd_entry_t fd_entry, static void _dispatch_io_dispose(dispatch_io_t channel) { - if (channel->fd_entry) { + if (channel->fd_entry && !(channel->atomic_flags & (DIO_CLOSED|DIO_STOPPED))) { if (channel->fd_entry->path_data) { // This modification is safe since path_data->channel is checked // only on close_queue (which is still suspended at this point) @@ -625,8 +625,10 @@ _dispatch_io_stop(dispatch_io_t channel) if (fd_entry) { _dispatch_io_debug("io stop cleanup", channel->fd); _dispatch_fd_entry_cleanup_operations(fd_entry, channel); - channel->fd_entry = NULL; - _dispatch_fd_entry_release(fd_entry); + if (!(channel->atomic_flags & DIO_CLOSED)) { + channel->fd_entry = NULL; + _dispatch_fd_entry_release(fd_entry); + } } else if (channel->fd != -1) { // Stop after close, need to check if fd_entry still exists _dispatch_retain(channel); @@ -667,9 +669,9 @@ dispatch_io_close(dispatch_io_t channel, unsigned long flags) dispatch_async(channel->queue, ^{ dispatch_async(channel->barrier_queue, ^{ _dispatch_io_debug("io close", channel->fd); - (void)dispatch_atomic_or2o(channel, atomic_flags, DIO_CLOSED); - dispatch_fd_entry_t fd_entry = channel->fd_entry; - if (fd_entry) { + if (!(channel->atomic_flags & (DIO_CLOSED|DIO_STOPPED))) { + (void)dispatch_atomic_or2o(channel, atomic_flags, DIO_CLOSED); + dispatch_fd_entry_t fd_entry = channel->fd_entry; if (!fd_entry->path_data) { channel->fd_entry = NULL; } @@ -1857,13 +1859,13 @@ _dispatch_disk_perform(void *ctxt) dispatch_async(disk->pick_queue, ^{ switch (result) { case DISPATCH_OP_DELIVER: - _dispatch_operation_deliver_data(op, DOP_DELIVER); + _dispatch_operation_deliver_data(op, DOP_DEFAULT); break; case DISPATCH_OP_COMPLETE: _dispatch_disk_complete_operation(disk, op); break; case DISPATCH_OP_DELIVER_AND_COMPLETE: - _dispatch_operation_deliver_data(op, DOP_DELIVER); + _dispatch_operation_deliver_data(op, DOP_DELIVER | DOP_NO_EMPTY); _dispatch_disk_complete_operation(disk, op); break; case DISPATCH_OP_ERR: @@ -2094,7 +2096,7 @@ _dispatch_operation_deliver_data(dispatch_operation_t op, data = dispatch_data_create_subrange(op->data, op->buf_len, op->length); } - if (op->buf_len == op->buf_siz) { + if (op->buf_data && op->buf_len == op->buf_siz) { _dispatch_io_data_release(op->buf_data); op->buf_data = NULL; op->buf = NULL; @@ -2105,7 +2107,7 @@ _dispatch_operation_deliver_data(dispatch_operation_t op, _dispatch_io_data_retain(data); d = data; } else { - d = dispatch_data_create_subrange(op->data, op->buf_len, + d = dispatch_data_create_subrange(op->data, op->buf_siz, op->length); } _dispatch_io_data_release(op->data); @@ -2123,7 +2125,6 @@ _dispatch_operation_deliver_data(dispatch_operation_t op, op->undelivered = 0; _dispatch_io_debug("deliver data", op->fd_entry->fd); dispatch_op_direction_t direction = op->direction; - __block dispatch_data_t d = data; dispatch_io_handler_t handler = op->handler; #if DISPATCH_IO_DEBUG int fd = op->fd_entry->fd; @@ -2135,6 +2136,7 @@ _dispatch_operation_deliver_data(dispatch_operation_t op, // Note that data delivery may occur after the operation is freed dispatch_async(op->op_q, ^{ bool done = (flags & DOP_DONE); + dispatch_data_t d = data; if (done) { if (direction == DOP_DIR_READ && err) { if (dispatch_data_get_size(d)) { diff --git a/src/source.c b/src/source.c index cf612aa..572912b 100644 --- a/src/source.c +++ b/src/source.c @@ -556,8 +556,9 @@ _dispatch_source_invoke(dispatch_source_t ds) return &_dispatch_mgr_q; } _dispatch_kevent_unregister(ds); - return ds->do_targetq; - } else if (dr->ds_cancel_handler) { + } + if (dr->ds_cancel_handler || ds->ds_handler_is_block || + ds->ds_registration_is_block) { if (dq != ds->do_targetq) { return ds->do_targetq; } @@ -603,7 +604,11 @@ _dispatch_source_probe(dispatch_source_t ds) // The source needs to be uninstalled from the manager queue, or the // cancellation handler needs to be delivered to the target queue. // Note: cancellation assumes installation. - if (ds->ds_dkev || dr->ds_cancel_handler) { + if (ds->ds_dkev || dr->ds_cancel_handler +#ifdef __BLOCKS__ + || ds->ds_handler_is_block || ds->ds_registration_is_block +#endif + ) { return true; } } else if (ds->ds_pending_data) { -- 2.45.2