diff --git a/src/system/kernel/device_manager/devfs.cpp b/src/system/kernel/device_manager/devfs.cpp index 090016419e..ecdc72a636 100644 --- a/src/system/kernel/device_manager/devfs.cpp +++ b/src/system/kernel/device_manager/devfs.cpp @@ -1615,9 +1615,8 @@ devfs_select(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, // If the device has no select() hook, notify select() now. if (!vnode->stream.u.dev.device->HasSelect()) { if (!SELECT_TYPE_IS_OUTPUT_ONLY(event)) - return notify_select_event((selectsync*)sync, event); - else - return B_OK; + notify_select_event((selectsync*)sync, event); + return B_UNSUPPORTED; } return vnode->stream.u.dev.device->Select(cookie->device_cookie, event, @@ -1635,7 +1634,6 @@ devfs_deselect(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, if (!S_ISCHR(vnode->stream.type)) return B_NOT_ALLOWED; - // If the device has no select() hook, notify select() now. if (!vnode->stream.u.dev.device->HasDeselect()) return B_OK; diff --git a/src/system/kernel/events/wait_for_objects.cpp b/src/system/kernel/events/wait_for_objects.cpp index 40bce55008..549516bad5 100644 --- a/src/system/kernel/events/wait_for_objects.cpp +++ b/src/system/kernel/events/wait_for_objects.cpp @@ -535,7 +535,7 @@ common_select(int numFDs, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, fd_zero(errorSet, numFDs); if (status == B_OK) { - for (count = 0, fd = 0;fd < numFDs; fd++) { + for (count = 0, fd = 0; fd < numFDs; fd++) { if (readSet && sync->set[fd].events & (SELECT_FLAG(B_SELECT_READ) | SELECT_FLAG(B_SELECT_DISCONNECTED) | SELECT_FLAG(B_SELECT_ERROR))) { FD_SET(fd, readSet); @@ -584,12 +584,16 @@ common_poll(struct pollfd *fds, nfds_t numFDs, bigtime_t timeout, int fd = fds[i].fd; // initialize events masks - sync->set[i].selected_events = fds[i].events - | POLLNVAL | POLLERR | POLLHUP; + fds[i].events |= POLLNVAL | POLLERR | POLLHUP; + sync->set[i].selected_events = fds[i].events; sync->set[i].events = 0; fds[i].revents = 0; if (fd >= 0 && select_fd(fd, sync->set + i, kernel) != B_OK) { + // If the FD returned events as well as an error, ignore the error. + if (sync->set[i].events != 0) + continue; + sync->set[i].events = POLLNVAL; fds[i].revents = POLLNVAL; // indicates that the FD doesn't need to be deselected @@ -634,8 +638,7 @@ common_poll(struct pollfd *fds, nfds_t numFDs, bigtime_t timeout, continue; // POLLxxx flags and B_SELECT_xxx flags are compatible - fds[i].revents = sync->set[i].events - & sync->set[i].selected_events; + fds[i].revents = sync->set[i].events & fds[i].events; if (fds[i].revents != 0) count++; } @@ -676,12 +679,16 @@ common_wait_for_objects(object_wait_info* infos, int numInfos, uint32 flags, int32 object = infos[i].object; // initialize events masks - sync->set[i].selected_events = infos[i].events - | B_EVENT_INVALID | B_EVENT_ERROR | B_EVENT_DISCONNECTED; + infos[i].events |= B_EVENT_INVALID | B_EVENT_ERROR | B_EVENT_DISCONNECTED; + sync->set[i].selected_events = infos[i].events; sync->set[i].events = 0; infos[i].events = 0; if (select_object(type, object, sync->set + i, kernel) != B_OK) { + // If the object returned events as well as an error, ignore the error. + if (sync->set[i].events != 0) + continue; + sync->set[i].events = B_EVENT_INVALID; infos[i].events = B_EVENT_INVALID; // indicates that the object doesn't need to be deselected @@ -708,8 +715,7 @@ common_wait_for_objects(object_wait_info* infos, int numInfos, uint32 flags, ssize_t count = 0; if (status == B_OK) { for (int i = 0; i < numInfos; i++) { - infos[i].events = sync->set[i].events - & sync->set[i].selected_events; + infos[i].events &= sync->set[i].events; if (infos[i].events != 0) count++; } diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index d85450c99e..cc21eac5f2 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -562,9 +562,10 @@ select_fd(int32 fd, struct select_info* info, bool kernel) // immediately notify the select call eventsToSelect &= ~SELECT_OUTPUT_ONLY_FLAGS; if (eventsToSelect != 0) - return notify_select_events(info, eventsToSelect); - else - return B_OK; + notify_select_events(info, eventsToSelect); + + info->selected_events = 0; + return B_UNSUPPORTED; } // We need the FD to stay open while we're doing this, so no select()/ diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 515578023d..f2b4919f72 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5847,9 +5847,8 @@ file_select(struct file_descriptor* descriptor, uint8 event, // If the FS has no select() hook, notify select() now. if (!HAS_FS_CALL(vnode, select)) { if (!SELECT_TYPE_IS_OUTPUT_ONLY(event)) - return notify_select_event(sync, event); - else - return B_OK; + notify_select_event(sync, event); + return B_UNSUPPORTED; } return FS_CALL(vnode, select, descriptor->cookie, event, sync);