unix: Use MP_STREAM_GET_FILENO to allow uselect to poll general objects.

This mechanism will scale to to an arbitrary number of pollable objects, so
long as they implement the MP_STREAM_GET_FILENO ioctl.  Since ussl objects
pass through ioctl requests transparently to the underlying socket object,
it will allow ussl sockets to be polled.  And a user object with uio.IOBase
as a base could support polling.
This commit is contained in:
Damien George 2018-07-20 13:09:49 +10:00
parent 7a4f1b00f6
commit ef554ef9a2
3 changed files with 14 additions and 12 deletions

View File

@ -124,6 +124,8 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
o->fd = -1;
#endif
return 0;
case MP_STREAM_GET_FILENO:
return o->fd;
default:
*errcode = EINVAL;
return MP_STREAM_ERROR;

View File

@ -34,6 +34,7 @@
#include <poll.h>
#include "py/runtime.h"
#include "py/stream.h"
#include "py/obj.h"
#include "py/objlist.h"
#include "py/objtuple.h"
@ -65,19 +66,15 @@ typedef struct _mp_obj_poll_t {
} mp_obj_poll_t;
STATIC int get_fd(mp_obj_t fdlike) {
int fd;
// Shortcut for fdfile compatible types
if (MP_OBJ_IS_TYPE(fdlike, &mp_type_fileio)
#if MICROPY_PY_SOCKET
|| MP_OBJ_IS_TYPE(fdlike, &mp_type_socket)
#endif
) {
mp_obj_fdfile_t *fdfile = MP_OBJ_TO_PTR(fdlike);
fd = fdfile->fd;
} else {
fd = mp_obj_get_int(fdlike);
if (MP_OBJ_IS_OBJ(fdlike)) {
const mp_stream_p_t *stream_p = mp_get_stream_raise(fdlike, MP_STREAM_OP_IOCTL);
int err;
mp_uint_t res = stream_p->ioctl(fdlike, MP_STREAM_GET_FILENO, 0, &err);
if (res != MP_STREAM_ERROR) {
return res;
}
}
return fd;
return mp_obj_get_int(fdlike);
}
/// \method register(obj[, eventmask])

View File

@ -123,6 +123,9 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
close(self->fd);
return 0;
case MP_STREAM_GET_FILENO:
return self->fd;
default:
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;