def send_impl(self, obj, channels=None): data = util.pickle.dumps(obj) # If no channels, just send the data. if not channels: self.sock.sendall(struct.pack('ii', len(data), 0)) self.sock.sendall(data) return # Construct the actual message. buf = bytearray(data) while len(buf) < 8: # Work around a Python bug where we need at least 8 bytes. buf.append(0) # Send the data length and # of channels. self.sock.sendall(struct.pack('ii', len(buf), len(channels))) cmsg = cmsghdr_t(len(channels)) for index, channel in enumerate(channels): cmsg.cmsg_data[index] = channel.fd buffer_t = ctypes.c_byte * len(buf) iov_base = buffer_t.from_buffer(buf) iovec = iovec_t() iovec.iov_base = ctypes.addressof(iov_base) iovec.iov_len = len(buf) msg = msghdr_t() msg.msg_name = None msg.msg_namelen = 0 msg.msg_iov = ctypes.pointer(iovec) msg.msg_iovlen = 1 msg.msg_control = ctypes.addressof(cmsg) msg.msg_controllen = cmsg.cmsg_len msg.msg_flags = 0 res = sendmsg(self.sock.fileno(), ctypes.pointer(msg), MSG_NOSIGNAL) check_errno(res) # On Linux, it's now safe to close all the channels we just sent. if util.IsLinux(): for channel in channels: channel.close()
MSG_CTRUNC = 0x20 def CMSG_NXTHDR(msg, cmsg): cmsg_len = cmsg.contents.cmsg_len if cmsg_len < ctypes.sizeof(cmsghdr_base_t): return None cmsg_len = Align(cmsg_len, ctypes.sizeof(ctypes.c_uint)) addr = ctypes.addressof(cmsg.contents) + cmsg_len check = addr + Align(ctypes.sizeof(cmsghdr_base_t), ctypes.sizeof(ctypes.c_uint)) if check > msg.msg_control + msg.msg_controllen: return None return ctypes.cast(addr, cmsghdr_base_t_p) elif util.IsLinux(): sLibC = ctypes.CDLL('libc.so.6', use_errno=True) pid_t = ctypes.c_int msg_socklen_t = ctypes.c_size_t SOL_SOCKET = 1 SCM_RIGHTS = 1 MSG_NOSIGNAL = 0x4000 MSG_CTRUNC = 0x8 class posix_spawn_file_actions_t(ctypes.Structure): _fields_ = [ ('allocated', ctypes.c_int), ('used', ctypes.c_int), ('spawn_action', ctypes.c_void_p), ('pad', ctypes.c_int * 16)