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)
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)
if (fd_entry) {
_dispatch_io_debug("io stop cleanup", channel->fd);
_dispatch_fd_entry_cleanup_operations(fd_entry, 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);
} else if (channel->fd != -1) {
// Stop after close, need to check if fd_entry still exists
_dispatch_retain(channel);
dispatch_async(channel->queue, ^{
dispatch_async(channel->barrier_queue, ^{
_dispatch_io_debug("io close", channel->fd);
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;
dispatch_async(disk->pick_queue, ^{
switch (result) {
case DISPATCH_OP_DELIVER:
dispatch_async(disk->pick_queue, ^{
switch (result) {
case DISPATCH_OP_DELIVER:
break;
case DISPATCH_OP_COMPLETE:
_dispatch_disk_complete_operation(disk, op);
break;
case DISPATCH_OP_DELIVER_AND_COMPLETE:
break;
case DISPATCH_OP_COMPLETE:
_dispatch_disk_complete_operation(disk, op);
break;
case DISPATCH_OP_DELIVER_AND_COMPLETE:
op->undelivered = 0;
_dispatch_io_debug("deliver data", op->fd_entry->fd);
dispatch_op_direction_t direction = op->direction;
op->undelivered = 0;
_dispatch_io_debug("deliver data", op->fd_entry->fd);
dispatch_op_direction_t direction = op->direction;
// Note that data delivery may occur after the operation is freed
dispatch_async(op->op_q, ^{
bool done = (flags & DOP_DONE);
// Note that data delivery may occur after the operation is freed
dispatch_async(op->op_q, ^{
bool done = (flags & DOP_DONE);