From: Serhiy Storchaka Date: Tue, 31 Oct 2017 14:13:52 +0000 (+0200) Subject: [2.7] bpo-31893: Fixed select.kqueue(). (GH-4166) (#4193) X-Git-Tag: v2.7.15rc1~151 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8cbf4e10646c3f5b8f0d274c2d7dea5bb6305f57;p=python [2.7] bpo-31893: Fixed select.kqueue(). (GH-4166) (#4193) * Fixed the layout of the kqueue_event structure on OpenBSD and NetBSD. * Fixed the comparison of the kqueue_event objects.. (cherry picked from commit b9052a0f91d2e83bbc27267247a5920c82b242a3) --- diff --git a/Misc/NEWS.d/next/Library/2017-10-29-13-51-01.bpo-31893.8LZKEz.rst b/Misc/NEWS.d/next/Library/2017-10-29-13-51-01.bpo-31893.8LZKEz.rst new file mode 100644 index 0000000000..46be7fb373 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-29-13-51-01.bpo-31893.8LZKEz.rst @@ -0,0 +1,2 @@ +Fixed the layout of the kqueue_event structure on OpenBSD and NetBSD. Fixed +the comparison of the kqueue_event objects. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index ce4c15b694..1260171388 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -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 @@ -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)}, @@ -1284,10 +1317,17 @@ kqueue_event_repr(kqueue_event_Object *s) char buf[1024]; PyOS_snprintf( buf, sizeof(buf), +#ifdef HAVE_LONG_LONG + "", + (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 "", - (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); } @@ -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 */ @@ -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); @@ -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: