n Tue, Jul 19, 2011 at 6:54 PM, Bastien ROUCARIES <roucaries.bastien@xxxxxxxxx> wrote: > I have some code if you want that work. If you could test, I wil lsend > you. I have no time to create m4 and proper gnulib integration. It is > up to you Please test, I do not even have compiled it. > Bastien > > On Tue, Jul 19, 2011 at 5:44 PM, Daniel P. Berrange <berrange@xxxxxxxxxx> wrote: >> On Tue, Jul 19, 2011 at 09:31:59AM -0600, Eric Blake wrote: >>> On 07/19/2011 09:30 AM, Daniel P. Berrange wrote: >>> >>I'm wondering if the problem here is that libvirt is trying to use the >>> >>pipe-to-self mechanism as a fundamental event loop idiom. That is, the >>> >>reason libvirt is calling poll is in order to minimize CPU until >>> >>something interesting happens, where interesting includes needing to >>> >>wake up a helper thread to do an action inside locks in response to the >>> >>receipt of a signal. >>> >> >>> >>Maybe you are on to something, and replacing all uses of pipe() with >>> >>virPipeToSelf() (which uses pipe() for efficiency on Linux, but >>> >>socketpair() on mingw), would allow libvirt to continue to use the >>> >>pipe-to-self idiom while also using fds that can actually be poll'd on >>> >>mingw. >>> > >>> >IIRC, we never resolved this for the last release. I think we should >>> >do as you suggest and just use socketpair() on Win32. Given the way >>> >in which libvirt uses these capabilities, I don't think the overheads >>> >of socketpair() vs pipe() are so onerous that we need worry about an >>> >even more fancy Win32 impl or eventfd for linux. Of course if someone >>> >wants todo a full job for gnulib meawhile, we won't complain... >>> >>> Well, right now, we don't even have socketpair() for Win32. We'd >>> have to wire up some other native APIs for this to work. >> >> Oh I read your mail above as indicating we did have socketpair() >> on Mingw32. A quick look through google, suggests most people >> go down the route of creating a TCP socket bound to localhost >> for this purpose. >> >> Daniel >> -- >> |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| >> |: http://libvirt.org -o- http://virt-manager.org :| >> |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| >> |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| >> >> >
/* Copyright (C) 2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <errno.h> /* memset */ #include <string.h> /* close */ #include <unistd.h> #include <sys/types.h> /* for socket, bind, accept, connect, listen */ #include <sys/socket.h> /* getaddrinfo_r */ #include <netdb.h> #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC 0 #endif #if !defined HAVE_SOCKETPAIR || 1 /* fake errno to something allowed by POSIX */ static int filtererrno (int e) { switch (e) { case EAFNOSUPPORT: case EMFILE: case ENFILE: case EOPNOTSUPP: case EPROTONOSUPPORT: case EPROTOTYPE: case EACCES: case EFAULT: case ENOBUFS: case ENOMEM: return e; default: return ENOMEM; } } /* filter out supported domain, type, protocol */ static int socketpairsupported (int domain, int type, int protocol) { (void) type; if (type != SOCK_DGRAM && type != SOCK_STREAM && type != SOCK_SEQPACKET && type != 0) return -1; #if HAVE_IPV4 if (domain == AF_INET) return AF_INET; #endif #if HAVE_IPV6 if(domain == AF_INET6) return AF_INET6; #endif #if HAVE_IPV6 || HAVE_IPV4 if(domain == AF_UNSPEC) return AF_UNSPEC; #endif return -1; } /* The socketpair() call creates an unnamed pair of connected sockets in the specified domain, of the specified type, and using the optionally specified protocol. This function create a socketpair using IPV4/IPV6 */ static int raw_socketpair_ipv46 (int domain, int rawtype, int protocol, int sv[2]) { #if HAVE_IPV6 || HAVE_IPV4 struct sockaddr_storage serverfd_addr, outsock_addr; socklen_t addr_len = sizeof (struct sockaddr_storage); struct addrinfo hints, *res; int getaddrinfo_r; int serverfd; int saved_errno; int insock, outsock; int type; int cloexecflag; int servertype; /* filter out cloexec flag */ cloexecflag = rawtype & SOCK_CLOEXEC; cloexecflag = 0; /* socket does not understand cloexec */ type = rawtype & ~SOCK_CLOEXEC; /* filter out protocol */ if (socketpairsupported (domain, type, protocol) < 0) { errno = EOPNOTSUPP; return -1; } if(domain == AF_UNSPEC) domain = HAVE_IPV6 ? AF_INET6 : AF_INET; if(type == 0) type = SOCK_STREAM; /* get loopback address */ memset (&hints, 0, sizeof (hints)); hints.ai_family = domain; hints.ai_socktype = type; hints.ai_protocol = protocol; hints.ai_flags = 0; getaddrinfo_r = getaddrinfo (NULL, "0", &hints, &res); /* fake errno */ switch (getaddrinfo_r) { case 0: break; case EAI_FAMILY: errno = EAFNOSUPPORT; return -1; case EAI_MEMORY: errno = ENOMEM; return -1; default: errno = EIO; return -1; } /* create server cloexec do not leak */ servertype = (type != SOCK_DGRAM ? type : type | cloexecflag); serverfd = socket (domain, servertype, protocol); if (-1 == serverfd) goto out_bind_fail; if (-1 == bind (serverfd, res->ai_addr, res->ai_addrlen)) goto out_close_serverfd; if (-1 == getsockname (serverfd, (struct sockaddr *) &serverfd_addr, &addr_len)) goto out_close_serverfd; if (type != SOCK_DGRAM) if (-1 == listen (serverfd, 1)) goto out_close_serverfd; outsock = socket (domain, type | cloexecflag, protocol); if (-1 == outsock) goto out_close_serverfd; if (type == SOCK_DGRAM) { if (-1 == bind (outsock, res->ai_addr, res->ai_addrlen)) goto out_close_outsock; if (-1 == getsockname (outsock, (struct sockaddr *) &outsock_addr, &addr_len)) goto out_close_outsock; } if (-1 == connect (outsock, (struct sockaddr *) &serverfd_addr, addr_len)) goto out_close_outsock; if (type != SOCK_DGRAM) { insock = accept4 (serverfd, NULL, NULL, cloexecflag); if (-1 == outsock) goto out_close_insock; /* do not check error, at most we leak serverfd */ (void) close (serverfd); } else { if (-1 == connect (serverfd, (struct sockaddr *) &outsock_addr, addr_len)) goto out_close_outsock; insock = serverfd; } sv[0] = insock; sv[1] = outsock; freeaddrinfo (res); return 0; out_close_insock: saved_errno = errno; (void) close (outsock); errno = saved_errno; out_close_outsock: saved_errno = errno; (void) close (insock); errno = saved_errno; out_close_serverfd: saved_errno = errno; (void) close (serverfd); errno = saved_errno; out_bind_fail: errno = filtererrno (errno); freeaddrinfo (res); return -1; #else errno = ENOSYS; return -1; #endif } /* The socketpair() call creates an unnamed pair of connected sockets in the specified domain, of the specified type, and using the optionally specified protocol. */ #if 0 int socketpair (int domain, int type, int protocol, int sv[2]) { return raw_socketpair_ipv46 (int domain, int type, int protocol, int sv[2]); } #endif #endif
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list