646 bail: |
648 bail: |
647 Py_DECREF(stats); |
649 Py_DECREF(stats); |
648 return NULL; |
650 return NULL; |
649 } |
651 } |
650 |
652 |
|
653 /* |
|
654 * recvfds() simply does not release GIL during blocking io operation because |
|
655 * command server is known to be single-threaded. |
|
656 */ |
|
657 |
|
658 static ssize_t recvfdstobuf(int sockfd, int **rfds, void *cbuf, size_t cbufsize) |
|
659 { |
|
660 char dummy[1]; |
|
661 struct iovec iov = {dummy, sizeof(dummy)}; |
|
662 struct msghdr msgh = {0}; |
|
663 struct cmsghdr *cmsg; |
|
664 |
|
665 msgh.msg_iov = &iov; |
|
666 msgh.msg_iovlen = 1; |
|
667 msgh.msg_control = cbuf; |
|
668 msgh.msg_controllen = (socklen_t)cbufsize; |
|
669 if (recvmsg(sockfd, &msgh, 0) < 0) |
|
670 return -1; |
|
671 |
|
672 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg; |
|
673 cmsg = CMSG_NXTHDR(&msgh, cmsg)) { |
|
674 if (cmsg->cmsg_level != SOL_SOCKET || |
|
675 cmsg->cmsg_type != SCM_RIGHTS) |
|
676 continue; |
|
677 *rfds = (int *)CMSG_DATA(cmsg); |
|
678 return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); |
|
679 } |
|
680 |
|
681 *rfds = cbuf; |
|
682 return 0; |
|
683 } |
|
684 |
|
685 static PyObject *recvfds(PyObject *self, PyObject *args) |
|
686 { |
|
687 int sockfd; |
|
688 int *rfds = NULL; |
|
689 ssize_t rfdscount, i; |
|
690 char cbuf[256]; |
|
691 PyObject *rfdslist = NULL; |
|
692 |
|
693 if (!PyArg_ParseTuple(args, "i", &sockfd)) |
|
694 return NULL; |
|
695 |
|
696 rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf)); |
|
697 if (rfdscount < 0) |
|
698 return PyErr_SetFromErrno(PyExc_OSError); |
|
699 |
|
700 rfdslist = PyList_New(rfdscount); |
|
701 if (!rfdslist) |
|
702 goto bail; |
|
703 for (i = 0; i < rfdscount; i++) { |
|
704 PyObject *obj = PyInt_FromLong(rfds[i]); |
|
705 if (!obj) |
|
706 goto bail; |
|
707 PyList_SET_ITEM(rfdslist, i, obj); |
|
708 } |
|
709 return rfdslist; |
|
710 |
|
711 bail: |
|
712 Py_XDECREF(rfdslist); |
|
713 return NULL; |
|
714 } |
|
715 |
651 #endif /* ndef _WIN32 */ |
716 #endif /* ndef _WIN32 */ |
652 |
717 |
653 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) |
718 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) |
654 { |
719 { |
655 PyObject *statobj = NULL; /* initialize - optional arg */ |
720 PyObject *statobj = NULL; /* initialize - optional arg */ |
814 "On error, this function may raise either a WindowsError or an IOError."}, |
879 "On error, this function may raise either a WindowsError or an IOError."}, |
815 #else |
880 #else |
816 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS, |
881 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS, |
817 "stat a series of files or symlinks\n" |
882 "stat a series of files or symlinks\n" |
818 "Returns None for non-existent entries and entries of other types.\n"}, |
883 "Returns None for non-existent entries and entries of other types.\n"}, |
|
884 {"recvfds", (PyCFunction)recvfds, METH_VARARGS, |
|
885 "receive list of file descriptors via socket\n"}, |
819 #endif |
886 #endif |
820 #ifdef __APPLE__ |
887 #ifdef __APPLE__ |
821 { |
888 { |
822 "isgui", (PyCFunction)isgui, METH_NOARGS, |
889 "isgui", (PyCFunction)isgui, METH_NOARGS, |
823 "Is a CoreGraphics session available?" |
890 "Is a CoreGraphics session available?" |