##// END OF EJS Templates
osutil: implement recvmsg() of SCM_RIGHTS for chg command server...
Yuya Nishihara -
r27473:34a37a2e default
parent child Browse files
Show More
@@ -11,6 +11,7 b''
11 #include <Python.h>
11 #include <Python.h>
12 #include <fcntl.h>
12 #include <fcntl.h>
13 #include <stdio.h>
13 #include <stdio.h>
14 #include <stdlib.h>
14 #include <string.h>
15 #include <string.h>
15 #include <errno.h>
16 #include <errno.h>
16
17
@@ -19,6 +20,7 b''
19 #include <io.h>
20 #include <io.h>
20 #else
21 #else
21 #include <dirent.h>
22 #include <dirent.h>
23 #include <sys/socket.h>
22 #include <sys/stat.h>
24 #include <sys/stat.h>
23 #include <sys/types.h>
25 #include <sys/types.h>
24 #include <unistd.h>
26 #include <unistd.h>
@@ -648,6 +650,69 b' bail:'
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)
@@ -816,6 +881,8 b' static PyMethodDef methods[] = {'
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 {
General Comments 0
You need to be logged in to leave comments. Login now