diff options
-rw-r--r-- | winsup/cygwin/ChangeLog | 54 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver.cc | 65 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_client.cc | 2 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_transport_pipes.cc | 68 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_transport_sockets.cc | 324 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver_transport.h | 6 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver_transport_pipes.h | 8 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver_transport_sockets.h | 15 |
8 files changed, 437 insertions, 105 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 88afcf96872..13b63e0bfc3 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,57 @@ 2002-07-27 Conrad Scott <conrad.scott@dsl.pipex.com> + * include/cygwin/cygserver_transport.h + (transport_layer_base::listen): Change return type. + (transport_layer_base::connect): Ditto. + * include/cygwin/cygserver_transport_pipes.h + (transport_layer_pipes::listen): Change return type. + (transport_layer_pipes::connect): Ditto. + (transport_layer_pipes::_sec_none_nih): Remove unused field. + (transport_layer_pipes::_is_listening_endpoint): New field. + * cygserver_transport_pipes.cc: Synchronize with sockets code. + (transport_layer_pipes::transport_layer_pipes): Initialise new + field. Separate out asserts. + (transport_layer_pipes::listen): Change return type. Add asserts. + (transport_layer_pipes::accept): Add asserts. + (transport_layer_pipes::read): Change conditional to an assert. + Add assert. + (transport_layer_pipes::write): Ditto. + (transport_layer_pipes::connect): Change return type. Change + conditional to an assert. Add asserts. Rationalize error code + slightly. + (transport_layer_pipes::impersonate_client): Add asserts. + * include/cygwin/cygserver_transport_sockets.h + (transport_layer_sockets::listen): Change return type. + (transport_layer_sockets::connect): Ditto. + (transport_layer_sockets::_addr): Change type of field. + (transport_layer_sockets::_addr_len): Ditto. + (transport_layer_sockets::_is_accepted_endpoint): New field. + (transport_layer_sockets::_is_listening_endpoint): Ditto. + * cygserver_transport_sockets.cc + (MAX_CONNECT_RETRY): New constant. + (transport_layer_sockets::transport_layer_sockets): Initialise new + fields. Only initialise the socket address where necessary. + (transport_layer_sockets::listen): Change return type. Rewrite. + (transport_layer_sockets::accept): Add asserts. Add tracing + statements. Use a local variable to hold the accepted address. + (transport_layer_sockets::close): Add tracing statements. Unlink + the UNIX domain socket file as appropriate. Close the socket + cleanly. + (transport_layer_sockets::read): Rewrite method. + (transport_layer_sockets::write): Ditto. + (transport_layer_sockets::connect): Change return type. Rewrite. + * cygserver.cc (server_submission_loop::request_loop): Run the + listening thread at high priority with special handling for + shutdown. + (main): Print the request error code rather than errno in shutdown + request code. Install signal handlers with sigaction(2) to avoid + setting SA_RESTART. Check value of the listen method call, now it + has one. + * cygserver_client.cc (client_request::make_request): Check new + return value on connect method call. + +2002-07-27 Conrad Scott <conrad.scott@dsl.pipex.com> + * include/cygwin/cygserver_transport_pipes.h (cygserver_transport_pipes::_sd): Rename field. (cygserver_transport_pipes::_sec_none_nih): Ditto. @@ -412,7 +464,7 @@ the SHM_INFO command. (server_shmmgr::shmget): Check `shmflg' against the mode of existing segments as per Stevens 1990, p. 123. - (server_shmmgr::server_shmmgr): Initialize the new `_shm_tot' + (server_shmmgr::server_shmmgr): Initialise the new `_shm_tot' field. (server_shmmgr::new_segment): Set ENOMEM if CreateFileMapping fails. Pass `size' to new_segment. diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc index 072c99cfd68..12161072b90 100755 --- a/winsup/cygwin/cygserver.cc +++ b/winsup/cygwin/cygserver.cc @@ -445,6 +445,20 @@ private: void server_submission_loop::request_loop () { + /* I'd like the accepting thread's priority to be above any "normal" + * thread in the system to avoid overflowing the listen queue (for + * sockets; similar issues exist for named pipes); but, for example, + * a normal priority thread in a foregrounded process is boosted to + * THREAD_PRIORITY_HIGHEST (AFAICT). Thus try to set the current + * thread's priority to a level one above that. This fails on + * win9x/ME so assume any failure in that call is due to that and + * simply call again at one priority level lower. + */ + if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1)) + if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST)) + debug_printf ("failed to raise accept thread priority, error = %lu", + GetLastError ()); + while (_running) { bool recoverable = false; @@ -454,6 +468,24 @@ server_submission_loop::request_loop () system_printf ("fatal error on IPC transport: closing down"); return; } + // EINTR probably implies a shutdown request; so back off for a + // moment to let the main thread take control, otherwise the + // server spins here receiving EINTR repeatedly since the signal + // handler in the main thread doesn't get a chance to be called. + if (!conn && errno == EINTR) + { + if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL)) + debug_printf ("failed to reset thread priority, error = %lu", + GetLastError ()); + + Sleep (0); + if (!SetThreadPriority (GetCurrentThread (), + THREAD_PRIORITY_HIGHEST + 1)) + if (!SetThreadPriority (GetCurrentThread (), + THREAD_PRIORITY_HIGHEST)) + debug_printf ("failed to raise thread priority, error = %lu", + GetLastError ()); + } if (conn) _queue->add (safe_new (server_request, conn, _cache)); } @@ -650,7 +682,7 @@ main (const int argc, char *argv[]) if (req.make_request () == -1 || req.error_code ()) { fprintf (stderr, "%s: shutdown request failed: %s\n", - pgm, strerror (errno)); + pgm, strerror (req.error_code ())); exit (1); } @@ -659,12 +691,26 @@ main (const int argc, char *argv[]) return 0; } - if (signal (SIGINT, handle_signal) == SIG_ERR) - { - system_printf ("could not install signal handler (%d)- aborting startup", - errno); - exit (1); - } +#define SIGHANDLE(SIG) \ + do \ + { \ + struct sigaction act; \ + \ + act.sa_handler = &handle_signal; \ + act.sa_mask = 0; \ + act.sa_flags = 0; \ + \ + if (sigaction (SIG, &act, NULL) == -1) \ + { \ + system_printf ("failed to install handler for " #SIG ": %s", \ + strerror (errno)); \ + exit (1); \ + } \ + } while (false) + + SIGHANDLE (SIGHUP); + SIGHANDLE (SIGINT); + SIGHANDLE (SIGTERM); print_version (pgm); setbuf (stdout, NULL); @@ -686,7 +732,10 @@ main (const int argc, char *argv[]) request_queue.add_submission_loop (&submission_loop); printf ("."); - transport->listen (); + if (transport->listen () == -1) + { + exit (1); + } printf ("."); cache.start (); diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc index 9ae7f6ba4ee..859fbcb9728 100755 --- a/winsup/cygwin/cygserver_client.cc +++ b/winsup/cygwin/cygserver_client.cc @@ -350,7 +350,7 @@ client_request::make_request () assert (transport); - if (!transport->connect ()) + if (transport->connect () == -1) { if (errno) error_code (errno); diff --git a/winsup/cygwin/cygserver_transport_pipes.cc b/winsup/cygwin/cygserver_transport_pipes.cc index 7668d6cc999..6e6f0a666e7 100755 --- a/winsup/cygwin/cygserver_transport_pipes.cc +++ b/winsup/cygwin/cygserver_transport_pipes.cc @@ -59,9 +59,11 @@ initialise_pipe_instance_lock () transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe) : _pipe_name (""), _hPipe (hPipe), - _is_accepted_endpoint (true) + _is_accepted_endpoint (true), + _is_listening_endpoint (false) { - assert (_hPipe && _hPipe != INVALID_HANDLE_VALUE); + assert (_hPipe); + assert (_hPipe != INVALID_HANDLE_VALUE); init_security (); } @@ -71,7 +73,8 @@ transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe) transport_layer_pipes::transport_layer_pipes () : _pipe_name ("\\\\.\\pipe\\cygwin_lpc"), _hPipe (NULL), - _is_accepted_endpoint (false) + _is_accepted_endpoint (false), + _is_listening_endpoint (false) { init_security (); } @@ -86,10 +89,9 @@ transport_layer_pipes::init_security () InitializeSecurityDescriptor (&_sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl (&_sd, TRUE, NULL, FALSE); - _sec_none_nih.nLength = _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES); - _sec_none_nih.bInheritHandle = _sec_all_nih.bInheritHandle = FALSE; - _sec_none_nih.lpSecurityDescriptor = NULL; + _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES); _sec_all_nih.lpSecurityDescriptor = &_sd; + _sec_all_nih.bInheritHandle = FALSE; } transport_layer_pipes::~transport_layer_pipes () @@ -99,19 +101,22 @@ transport_layer_pipes::~transport_layer_pipes () #ifndef __INSIDE_CYGWIN__ -void +int transport_layer_pipes::listen () { - assert (!_is_accepted_endpoint); assert (!_hPipe); + assert (!_is_accepted_endpoint); + assert (!_is_listening_endpoint); /* no-op */ + return 0; } class transport_layer_pipes * transport_layer_pipes::accept (bool *const recoverable) { - assert (!_is_accepted_endpoint); assert (!_hPipe); + assert (!_is_accepted_endpoint); + assert (_is_listening_endpoint); pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock); @@ -145,8 +150,8 @@ transport_layer_pipes::accept (bool *const recoverable) if (duplicate) { *recoverable = false; - system_printf ("failure creating named pipe: " - "is there another instance of the server running?"); + system_printf ("failed to create named pipe: " + "is the daemon already running?"); return NULL; } @@ -213,13 +218,9 @@ transport_layer_pipes::read (void *const buf, const size_t len) { // verbose: debug_printf ("reading from pipe %p", _hPipe); - if (!_hPipe) - { - set_errno (EBADF); - return -1; - } - + assert (_hPipe); assert (_hPipe != INVALID_HANDLE_VALUE); + assert (!_is_listening_endpoint); DWORD count; if (!ReadFile (_hPipe, buf, len, &count, NULL)) @@ -237,13 +238,9 @@ transport_layer_pipes::write (void *const buf, const size_t len) { // verbose: debug_printf ("writing to pipe %p", _hPipe); - if (!_hPipe) - { - set_errno (EBADF); - return -1; - } - + assert (_hPipe); assert (_hPipe != INVALID_HANDLE_VALUE); + assert (!_is_listening_endpoint); DWORD count; if (!WriteFile (_hPipe, buf, len, &count, NULL)) @@ -265,16 +262,12 @@ transport_layer_pipes::write (void *const buf, const size_t len) * congestion and overloading problems. */ -bool +int transport_layer_pipes::connect () { - if (_hPipe) - { - assert (_hPipe != INVALID_HANDLE_VALUE); - - debug_printf ("Already have a pipe in this %p",this); - return false; - } + assert (!_hPipe); + assert (!_is_accepted_endpoint); + assert (!_is_listening_endpoint); static bool assume_cygserver = false; @@ -298,18 +291,17 @@ transport_layer_pipes::connect () ProtectHandle (_hPipe); #endif assume_cygserver = true; - return true; + return 0; } + _hPipe = NULL; + if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY) { debug_printf ("Error opening the pipe (%lu)", GetLastError ()); - _hPipe = NULL; - return false; + return -1; } - _hPipe = NULL; - /* Note: `If no instances of the specified named pipe exist, the * WaitNamedPipe function returns immediately, regardless of the * time-out value.' Thus the explicit Sleep if the call fails @@ -332,7 +324,7 @@ transport_layer_pipes::connect () assume_cygserver = false; - return false; + return -1; } #ifndef __INSIDE_CYGWIN__ @@ -340,6 +332,8 @@ transport_layer_pipes::connect () void transport_layer_pipes::impersonate_client () { + assert (_hPipe); + assert (_hPipe != INVALID_HANDLE_VALUE); assert (_is_accepted_endpoint); // verbose: debug_printf ("impersonating pipe %p", _hPipe); diff --git a/winsup/cygwin/cygserver_transport_sockets.cc b/winsup/cygwin/cygserver_transport_sockets.cc index a2f8131dbf1..17f0f9bce0f 100755 --- a/winsup/cygwin/cygserver_transport_sockets.cc +++ b/winsup/cygwin/cygserver_transport_sockets.cc @@ -17,12 +17,15 @@ details. */ #include "winsup.h" #endif +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <assert.h> #include <errno.h> #include <stdio.h> #include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> + #include "cygwin/cygserver_transport.h" #include "cygwin/cygserver_transport_sockets.h" @@ -33,6 +36,7 @@ extern "C" int cygwin_accept (int fd, struct sockaddr *, int *len); extern "C" int cygwin_bind (int fd, const struct sockaddr *, int len); extern "C" int cygwin_connect (int fd, const struct sockaddr *, int len); extern "C" int cygwin_listen (int fd, int backlog); +extern "C" int cygwin_shutdown (int fd, int how); extern "C" int cygwin_socket (int af, int type, int protocol); #else /* __OUTSIDE_CYGWIN__ */ @@ -41,26 +45,38 @@ extern "C" int cygwin_socket (int af, int type, int protocol); #define cygwin_bind(A,B,C) ::bind (A,B,C) #define cygwin_connect(A,B,C) ::connect (A,B,C) #define cygwin_listen(A,B) ::listen (A,B) +#define cygwin_shutdown(A,B) ::shutdown (A,B) #define cygwin_socket(A,B,C) ::socket (A,B,C) #endif /* __OUTSIDE_CYGWIN__ */ -transport_layer_sockets::transport_layer_sockets (int newfd) - : _fd (newfd) +enum + { + MAX_CONNECT_RETRY = 64 + }; + +transport_layer_sockets::transport_layer_sockets (const int fd) + : _fd (fd), + _addr_len (0), + _is_accepted_endpoint (true), + _is_listening_endpoint (false) { - /* This may not be needed in this constructor - it's only used - * when creating a connection via bind or connect - */ - _addr.sa_family = AF_UNIX; - strcpy (_addr.sa_data, "/tmp/cygdaemo"); - _addr_len = strlen (_addr.sa_data) + sizeof (_addr.sa_family); -}; - -transport_layer_sockets::transport_layer_sockets (): _fd (-1) + assert (_fd != -1); + + memset (&_addr, '\0', sizeof (_addr)); +} + +transport_layer_sockets::transport_layer_sockets () + : _fd (-1), + _addr_len (0), + _is_accepted_endpoint (false), + _is_listening_endpoint (false) { - _addr.sa_family = AF_UNIX; - strcpy (_addr.sa_data, "/tmp/cygdaemo"); - _addr_len = strlen (_addr.sa_data) + sizeof (_addr.sa_family); + memset (&_addr, '\0', sizeof (_addr)); + + _addr.sun_family = AF_UNIX; + strcpy (_addr.sun_path, "/tmp/cygdaemo"); // FIXME: $TMP? + _addr_len = SUN_LEN (&_addr); } transport_layer_sockets::~transport_layer_sockets () @@ -70,28 +86,119 @@ transport_layer_sockets::~transport_layer_sockets () #ifndef __INSIDE_CYGWIN__ -void +int transport_layer_sockets::listen () { - /* we want a thread pool based approach. */ - if ((_fd = cygwin_socket (AF_UNIX, SOCK_STREAM,0)) < 0) - system_printf ("Socket not created error %d", errno); - if (cygwin_bind (_fd, &_addr, _addr_len)) - system_printf ("Bind doesn't like you. Tsk Tsk. Bind said %d", errno); - if (cygwin_listen (_fd, 5) < 0) - system_printf ("And the OS just isn't listening, all it says is %d", - errno); + assert (_fd == -1); + assert (!_is_accepted_endpoint); + assert (!_is_listening_endpoint); + + debug_printf ("listen () [this = %p]", this); + + struct stat sbuf; + + if (stat (_addr.sun_path, &sbuf) == -1) + { + if (errno != ENOENT) + { + system_printf ("cannot access socket file `%s': %s", + _addr.sun_path, strerror (errno)); + return -1; + } + } + else if (S_ISSOCK (sbuf.st_mode)) + { + // The socket already exists: is a duplicate cygserver running? + + const int newfd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); + + if (newfd == -1) + { + system_printf ("failed to create UNIX domain socket: %s", + strerror (errno)); + return -1; + } + + if (cygwin_connect (newfd, (struct sockaddr *) &_addr, _addr_len) == 0) + { + system_printf ("the daemon is already running"); + (void) cygwin_shutdown (newfd, SHUT_WR); + char buf[BUFSIZ]; + while (::read (newfd, buf, sizeof (buf)) > 0) + {} + (void) ::close (newfd); + return -1; + } + + if (unlink (_addr.sun_path) == -1) + { + system_printf ("failed to remove `%s': %s", + _addr.sun_path, strerror (errno)); + (void) ::close (newfd); + return -1; + } + } + else + { + system_printf ("cannot create socket `%s': File already exists", + _addr.sun_path); + return -1; + } + + _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); + + if (_fd == -1) + { + system_printf ("failed to create UNIX domain socket: %s", + strerror (errno)); + return -1; + } + + if (cygwin_bind (_fd, (struct sockaddr *) &_addr, _addr_len) == -1) + { + const int saved_errno = errno; + close (); + errno = saved_errno; + system_printf ("failed to bind UNIX domain socket `%s': %s", + _addr.sun_path, strerror (errno)); + return -1; + } + + _is_listening_endpoint = true; // i.e. this really means "have bound". + + if (cygwin_listen (_fd, SOMAXCONN) == -1) + { + const int saved_errno = errno; + close (); + errno = saved_errno; + system_printf ("failed to listen on UNIX domain socket `%s': %s", + _addr.sun_path, strerror (errno)); + return -1; + } + + debug_printf ("0 = listen () [this = %p, fd = %d]", this, _fd); + + return 0; } class transport_layer_sockets * transport_layer_sockets::accept (bool *const recoverable) { - /* FIXME: check we have listened */ - const int accept_fd = cygwin_accept (_fd, &_addr, &_addr_len); + assert (_fd != -1); + assert (!_is_accepted_endpoint); + assert (_is_listening_endpoint); + + debug_printf ("accept () [this = %p, fd = %d]", this, _fd); + + struct sockaddr_un client_addr; + socklen_t client_addr_len = sizeof (client_addr); + + const int accept_fd = + cygwin_accept (_fd, (struct sockaddr *) &client_addr, &client_addr_len); if (accept_fd == -1) { - system_printf ("Nup, couldn't accept. %d", errno); + system_printf ("failed to accept connection: %s", strerror (errno)); switch (errno) { case ECONNABORTED: @@ -110,6 +217,8 @@ transport_layer_sockets::accept (bool *const recoverable) return NULL; } + debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd); + return safe_new (transport_layer_sockets, accept_fd); } @@ -118,40 +227,161 @@ transport_layer_sockets::accept (bool *const recoverable) void transport_layer_sockets::close () { - /* FIXME - are we open? */ + debug_printf ("close () [this = %p, fd = %d]", this, _fd); + + if (_is_listening_endpoint) + (void) unlink (_addr.sun_path); + if (_fd != -1) { - ::close (_fd); + (void) cygwin_shutdown (_fd, SHUT_WR); + if (!_is_listening_endpoint) + { + char buf[BUFSIZ]; + while (::read (_fd, buf, sizeof (buf)) > 0) + {} + } + (void) ::close (_fd); _fd = -1; } + + _is_listening_endpoint = false; } ssize_t -transport_layer_sockets::read (void *buf, size_t len) +transport_layer_sockets::read (void *const buf, const size_t buf_len) { - /* FIXME: are we open? */ - return ::read (_fd, buf, len); + assert (_fd != -1); + assert (!_is_listening_endpoint); + + assert (buf); + assert (buf_len > 0); + + // verbose: debug_printf ("read (buf = %p, len = %u) [this = %p, fd = %d]", + // buf, buf_len, this, _fd); + + char *read_buf = static_cast<char *>(buf); + size_t read_buf_len = buf_len; + ssize_t res = 0; + + while (read_buf_len != 0 + && (res = ::read (_fd, read_buf, read_buf_len)) > 0) + { + read_buf += res; + read_buf_len -= res; + + assert (read_buf_len >= 0); + } + + if (res != -1) + { + if (res == 0) + errno = EIO; // FIXME? + + res = buf_len - read_buf_len; + } + + if (res != static_cast<ssize_t>(buf_len)) + debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]: %s", + res, buf, buf_len, this, _fd, + (res == -1 ? strerror (errno) : "EOF")); + else + { + // verbose: debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]", + // res, buf, buf_len, this, _fd); + } + + return res; } ssize_t -transport_layer_sockets::write (void *buf, size_t len) +transport_layer_sockets::write (void *const buf, const size_t buf_len) { - /* FIXME: are we open? */ - return ::write (_fd, buf, len); + assert (_fd != -1); + assert (!_is_listening_endpoint); + + assert (buf); + assert (buf_len > 0); + + // verbose: debug_printf ("write (buf = %p, len = %u) [this = %p, fd = %d]", + // buf, buf_len, this, _fd); + + char *write_buf = static_cast<char *>(buf); + size_t write_buf_len = buf_len; + ssize_t res = 0; + + while (write_buf_len != 0 + && (res = ::write (_fd, write_buf, write_buf_len)) > 0) + { + write_buf += res; + write_buf_len -= res; + + assert (write_buf_len >= 0); + } + + if (res != -1) + { + if (res == 0) + errno = EIO; // FIXME? + + res = buf_len - write_buf_len; + } + + if (res != static_cast<ssize_t>(buf_len)) + debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]: %s", + res, buf, buf_len, this, _fd, + (res == -1 ? strerror (errno) : "EOF")); + else + { + // verbose: debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]", + // res, buf, buf_len, this, _fd); + } + + return res; } -bool +int transport_layer_sockets::connect () { - /* are we already connected? */ - if (_fd != -1) - return false; - _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); - if (cygwin_connect (_fd, &_addr, _addr_len) < 0) + assert (_fd == -1); + assert (!_is_accepted_endpoint); + assert (!_is_listening_endpoint); + + static bool assume_cygserver = false; + + debug_printf ("connect () [this = %p]", this); + + for (int retries = 0; retries != MAX_CONNECT_RETRY; retries++) { - debug_printf ("client connect failure %d", errno); - ::close (_fd); - return false; + _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); + + if (_fd == -1) + { + system_printf ("failed to create UNIX domain socket: %s", + strerror (errno)); + return -1; + } + + if (cygwin_connect (_fd, (struct sockaddr *) &_addr, _addr_len) == 0) + { + assume_cygserver = true; + debug_printf ("0 = connect () [this = %p, fd = %d]", this, _fd); + return 0; + } + + if (!assume_cygserver || errno != ECONNREFUSED) + { + debug_printf ("failed to connect to server: %s", strerror (errno)); + (void) ::close (_fd); + _fd = -1; + return -1; + } + + (void) ::close (_fd); + _fd = -1; + Sleep (0); // Give the server a chance. } - return true; + + debug_printf ("failed to connect to server: %s", strerror (errno)); + return -1; } diff --git a/winsup/cygwin/include/cygwin/cygserver_transport.h b/winsup/cygwin/include/cygwin/cygserver_transport.h index c18486c1c71..915f35e6651 100755 --- a/winsup/cygwin/include/cygwin/cygserver_transport.h +++ b/winsup/cygwin/include/cygwin/cygserver_transport.h @@ -13,20 +13,20 @@ details. */ #ifndef _CYGSERVER_TRANSPORT_ #define _CYGSERVER_TRANSPORT_ -class transport_layer_base *create_server_transport(); +class transport_layer_base *create_server_transport (); class transport_layer_base { public: #ifndef __INSIDE_CYGWIN__ - virtual void listen () = 0; + virtual int listen () = 0; virtual class transport_layer_base *accept (bool *recoverable) = 0; #endif virtual void close () = 0; virtual ssize_t read (void *buf, size_t len) = 0; virtual ssize_t write (void *buf, size_t len) = 0; - virtual bool connect () = 0; + virtual int connect () = 0; #ifndef __INSIDE_CYGWIN__ virtual void impersonate_client (); diff --git a/winsup/cygwin/include/cygwin/cygserver_transport_pipes.h b/winsup/cygwin/include/cygwin/cygserver_transport_pipes.h index fe571a77085..4bea2eb134b 100755 --- a/winsup/cygwin/include/cygwin/cygserver_transport_pipes.h +++ b/winsup/cygwin/include/cygwin/cygserver_transport_pipes.h @@ -18,14 +18,14 @@ class transport_layer_pipes : public transport_layer_base { public: #ifndef __INSIDE_CYGWIN__ - virtual void listen (); + virtual int listen (); virtual class transport_layer_pipes *accept (bool *recoverable); #endif virtual void close (); virtual ssize_t read (void *buf, size_t len); virtual ssize_t write (void *buf, size_t len); - virtual bool connect (); + virtual int connect (); #ifndef __INSIDE_CYGWIN__ virtual void impersonate_client (); @@ -38,12 +38,14 @@ public: private: /* for pipe based communications */ void init_security (); + //FIXME: allow inited, sd, all_nih_.. to be static members SECURITY_DESCRIPTOR _sd; - SECURITY_ATTRIBUTES _sec_none_nih, _sec_all_nih; + SECURITY_ATTRIBUTES _sec_all_nih; const char *const _pipe_name; HANDLE _hPipe; const bool _is_accepted_endpoint; + bool _is_listening_endpoint; transport_layer_pipes (HANDLE hPipe); }; diff --git a/winsup/cygwin/include/cygwin/cygserver_transport_sockets.h b/winsup/cygwin/include/cygwin/cygserver_transport_sockets.h index 97d3baa2303..d960f9c2c52 100755 --- a/winsup/cygwin/include/cygwin/cygserver_transport_sockets.h +++ b/winsup/cygwin/include/cygwin/cygserver_transport_sockets.h @@ -13,18 +13,21 @@ details. */ #ifndef _CYGSERVER_TRANSPORT_SOCKETS_ #define _CYGSERVER_TRANSPORT_SOCKETS_ +#include <sys/socket.h> +#include <sys/un.h> + class transport_layer_sockets : public transport_layer_base { public: #ifndef __INSIDE_CYGWIN__ - virtual void listen (); + virtual int listen (); virtual class transport_layer_sockets *accept (bool *recoverable); #endif virtual void close (); virtual ssize_t read (void *buf, size_t len); virtual ssize_t write (void *buf, size_t len); - virtual bool connect (); + virtual int connect (); transport_layer_sockets (); virtual ~transport_layer_sockets (); @@ -32,10 +35,12 @@ public: private: /* for socket based communications */ int _fd; - struct sockaddr _addr; - int _addr_len; + struct sockaddr_un _addr; + socklen_t _addr_len; + const bool _is_accepted_endpoint; + bool _is_listening_endpoint; - transport_layer_sockets (int newfd); + transport_layer_sockets (int fd); }; #endif /* _CYGSERVER_TRANSPORT_SOCKETS_ */ |