Show More
@@ -11,6 +11,7 b'' | |||
|
11 | 11 | #include <Python.h> |
|
12 | 12 | #include <fcntl.h> |
|
13 | 13 | #include <stdio.h> |
|
14 | #include <stdlib.h> | |
|
14 | 15 | #include <string.h> |
|
15 | 16 | #include <errno.h> |
|
16 | 17 | |
@@ -19,6 +20,7 b'' | |||
|
19 | 20 | #include <io.h> |
|
20 | 21 | #else |
|
21 | 22 | #include <dirent.h> |
|
23 | #include <sys/socket.h> | |
|
22 | 24 | #include <sys/stat.h> |
|
23 | 25 | #include <sys/types.h> |
|
24 | 26 | #include <unistd.h> |
@@ -648,6 +650,69 b' bail:' | |||
|
648 | 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 | 716 | #endif /* ndef _WIN32 */ |
|
652 | 717 | |
|
653 | 718 | static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) |
@@ -816,6 +881,8 b' static PyMethodDef methods[] = {' | |||
|
816 | 881 | {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS, |
|
817 | 882 | "stat a series of files or symlinks\n" |
|
818 | 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 | 886 | #endif |
|
820 | 887 | #ifdef __APPLE__ |
|
821 | 888 | { |
General Comments 0
You need to be logged in to leave comments.
Login now