8000 [2.7] bpo-31893: Fixed select.kqueue(). (GH-4166) by serhiy-storchaka · Pull Request #4193 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content
< 8000 div class="gh-header-show ">

[2.7] bpo-31893: Fixed select.kqueue(). (GH-4166) #4193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed the layout of the kqueue_event structure on OpenBSD and NetBSD. Fixed
the comparison of the kqueue_event objects.
132 changes: 84 additions & 48 deletions Modules/selectmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,43 +1221,76 @@ static PyTypeObject kqueue_queue_Type;

#if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P)
# error uintptr_t does not match void *!
#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG)
#elif defined(HAVE_LONG_LONG) && (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG)
# define T_UINTPTRT T_ULONGLONG
# define T_INTPTRT T_LONGLONG
# define PyLong_AsUintptr_t PyLong_AsUnsignedLongLong
# define UINTPTRT_FMT_UNIT "K"
# define INTPTRT_FMT_UNIT "L"
#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG)
# define T_UINTPTRT T_ULONG
# define T_INTPTRT T_LONG
# define PyLong_AsUintptr_t PyLong_AsUnsignedLong
# define UINTPTRT_FMT_UNIT "k"
# define INTPTRT_FMT_UNIT "l"
#elif (SIZEOF_UINTPTR_T == SIZEOF_INT)
# define T_UINTPTRT T_UINT
# define T_INTPTRT T_INT
# define PyLong_AsUintptr_t PyLong_AsUnsignedLong
# define UINTPTRT_FMT_UNIT "I"
# define INTPTRT_FMT_UNIT "i"
#else
# error uintptr_t does not match int, long, or long long!
#endif

#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
# define T_INT64 T_LONGLONG
# define INT64_FMT_UNIT "L"
#elif SIZEOF_LONG == 8
# define T_INT64 T_LONG
# define INT64_FMT_UNIT "l"
#elif SIZEOF_INT == 8
# define T_INT64 T_INT
# define INT64_FMT_UNIT "i"
#else
# define INT64_FMT_UNIT "_"
#endif

#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 4
# define T_UINT32 T_ULONGLONG
# define UINT32_FMT_UNIT "K"
#elif SIZEOF_LONG == 4
# define T_UINT32 T_ULONG
# define UINT32_FMT_UNIT "k"
#elif SIZEOF_INT == 4
# define T_UINT32 T_UINT
# define UINT32_FMT_UNIT "I"
#else
# define UINT32_FMT_UNIT "_"
#endif

/*
* kevent is not standard and its members vary across BSDs.
*/
#if !defined(__OpenBSD__)
# define IDENT_TYPE T_UINTPTRT
# define IDENT_CAST Py_intptr_t
# define DATA_TYPE T_INTPTRT
# define DATA_FMT_UNIT INTPTRT_FMT_UNIT
# define IDENT_AsType PyLong_AsUintptr_t
#ifdef __NetBSD__
# define FILTER_TYPE T_UINT32
# define FILTER_FMT_UNIT UINT32_FMT_UNIT
# define FLAGS_TYPE T_UINT32
# define FLAGS_FMT_UNIT UINT32_FMT_UNIT
# define FFLAGS_TYPE T_UINT32
# define FFLAGS_FMT_UNIT UINT32_FMT_UNIT
#else
# define IDENT_TYPE T_UINT
# define IDENT_CAST int
# define DATA_TYPE T_INT
# define DATA_FMT_UNIT "i"
# define IDENT_AsType PyLong_AsUnsignedLong
# define FILTER_TYPE T_SHORT
# define FILTER_FMT_UNIT "h"
# define FLAGS_TYPE T_USHORT
# define FLAGS_FMT_UNIT "H"
# define FFLAGS_TYPE T_UINT
# define FFLAGS_FMT_UNIT "I"
#endif

#ifdef __FreeBSD__
# define DATA_TYPE T_INTPTRT
# define DATA_FMT_UNIT INTPTR_FMT_UNIT
#else
# define DATA_TYPE T_INT64
# define DATA_FMT_UNIT INT64_FMT_UNIT
#endif

/* Unfortunately, we can't store python objects in udata, because
Expand All @@ -1267,9 +1300,9 @@ static PyTypeObject kqueue_queue_Type;

#define KQ_OFF(x) offsetof(kqueue_event_Object, x)
static struct PyMemberDef kqueue_event_members[] = {
{"ident", IDENT_TYPE, KQ_OFF(e.ident)},
{"filter", T_SHORT, KQ_OFF(e.filter)},
{"flags", T_USHORT, KQ_OFF(e.flags)},
{"ident", T_UINTPTRT, KQ_OFF(e.ident)},
{"filter", FILTER_TYPE, KQ_OFF(e.filter)},
{"flags", FLAGS_TYPE, KQ_OFF(e.flags)},
{"fflags", T_UINT, KQ_OFF(e.fflags)},
{"data", DATA_TYPE, KQ_OFF(e.data)},
{"udata", T_UINTPTRT, KQ_OFF(e.udata)},
Expand All @@ -1284,10 +1317,17 @@ kqueue_event_repr(kqueue_event_Object *s)
char buf[1024];
PyOS_snprintf(
buf, sizeof(buf),
#ifdef HAVE_LONG_LONG
"<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x "
"data=0x%llx udata=%p>",
(size_t)(s->e.ident), (int)s->e.filter, (unsigned int)s->e.flags,
(unsigned int)s->e.fflags, (long long)(s->e.data), (void *)s->e.udata);
#else
"<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x "
"data=0x%zd udata=%p>",
(size_t)(s->e.ident), s->e.filter, s->e.flags,
s->e.fflags, (Py_ssize_t)(s->e.data), s->e.udata);
"data=0x%llx udata=%p>",
(size_t)(s->e.ident), (int)s->e.filter, (unsigned int)s->e.flags,
(unsigned int)s->e.fflags, (long)(s->e.data), (void *)s->e.udata);
#endif
return PyString_FromString(buf);
}

Expand All @@ -1297,7 +1337,9 @@ kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds)
PyObject *pfd;
static char *kwlist[] = {"ident", "filter", "flags", "fflags",
"data", "udata", NULL};
static char *fmt = "O|hHI" DATA_FMT_UNIT UINTPTRT_FMT_UNIT ":kevent";
static const char fmt[] = "O|"
FILTER_FMT_UNIT FLAGS_FMT_UNIT FFLAGS_FMT_UNIT DATA_FMT_UNIT
UINTPTRT_FMT_UNIT ":kevent";

EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */

Expand All @@ -1307,12 +1349,12 @@ kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds)
return -1;
}

if (PyLong_Check(pfd)
#if IDENT_TYPE == T_UINT
&& PyLong_AsUnsignedLong(pfd) <= UINT_MAX
#endif
) {
self->e.ident = IDENT_AsType(pfd);
if (PyInt_Check(pfd)) {
self->e.ident = PyInt_AsUnsignedLongMask(pfd);
}
else {
if (PyInt_Check(pfd) || PyLong_Check(pfd)) {
self->e.ident = PyLong_AsSize_t(pfd);
}
else {
self->e.ident = PyObject_AsFileDescriptor(pfd);
Expand All @@ -1327,28 +1369,22 @@ static PyObject *
kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,
int op)
{
Py_intptr_t result = 0;
int result;

if (!kqueue_event_Check(o)) {
if (op == Py_EQ || op == Py_NE) {
PyObject *res = op == Py_EQ ? Py_False : Py_True;
Py_INCREF(res);
return res;
}
PyErr_Format(PyExc_TypeError,
"can't compare %.200s to %.200s",
Py_TYPE(s)->tp_name, Py_TYPE(o)->tp_name);
return NULL;
}
if (((result = (IDENT_CAST)(s->e.ident - o->e.ident)) == 0) &&
((result = s->e.filter - o->e.filter) == 0) &&
((result = s->e.flags - o->e.flags) == 0) &&
((result = (int)(s->e.fflags - o->e.fflags)) == 0) &&
((result = s->e.data - o->e.data) == 0) &&
((result = s->e.udata - o->e.udata) == 0)
) {
result = 0;
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}

#define CMP(a, b) ((a) != (b)) ? ((a) < (b) ? -1 : 1)
result = CMP(s->e.ident, o->e.ident)
: CMP(s->e.filter, o->e.filter)
: CMP(s->e.flags, o->e.flags)
: CMP(s->e.fflags, o->e.fflags)
: CMP(s->e.data, o->e.data)
: CMP((Py_intptr_t)s->e.udata, (Py_intptr_t)o->e.udata)
: 0;
#undef CMP

switch (op) {
case Py_EQ:
Expand Down
0