* dtable.cc (dtable::release): Check for socket. Change

cnt_need_fixup_before accordingly.
        (dtable::dup2): Ditto.
        (dtable::fixup_before_fork): New method.
        (dtable::fixup_before_exec): Ditto.
        * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add
        definition for methods `dec_need_fixup_before', `inc_need_fixup_before',
        `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'.
        * fhandler.h (class fhandler_base): Slight rearrangements. Add
        definitions for methods `fixup_before_fork_exec'.
        (class fhandler_socket): Eliminate superfluous constructor.
        Add member `prot_info_ptr'. Add destructor. Add definitions for
        methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and
        `fixup_after_exec'.
        * fork.cc (fork_parent): Care for file types which need a fixup
        before fork. Start child in suspended state then.
        * net.cc: New global variable `ws2_32_handle' and `wsadata'.
        (fdsock): Check for Winsock version. Call `set_socket_inheritance'
        only if Winsock version < 2.0. Care for `need_fixup' count in fdtab.
        (cygwin_socket): Eliminate call to `set_socket_inheritance'.
        (cygwin_accept): Ditto.
        (cygwin_rcmd): Ditto.
        (cygwin_rresvport): Ditto.
        (cygwin_rexec): Ditto.
        (socketpair): Ditto.
        (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate
        space for the WSAPROTOCOL_INFOA struct used in fixup.
        (fhandler_socket::~fhandler_socket): New destructor.
        (fhandler_socket::fixup_before_fork_exec): New method.
        (fhandler_socket::fixup_after_fork): Ditto.
        (fhandler_socket::dup): Ditto.
        (wsock_init): New static function.
        (LoadDLLinitfunc (wsock32)): Rearranged.
        (LoadDLLinitfunc (ws2_32)): New function.
        (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA'
        and `WSASocketA'.
        * spawn.cc (spawn_guts): Care for file types which need a fixup
        before exec. Start child in suspended state then.
This commit is contained in:
Corinna Vinschen 2000-10-26 10:13:41 +00:00
parent 003303a435
commit dd4f0b2343
7 changed files with 264 additions and 46 deletions

View File

@ -1,3 +1,44 @@
Thu Oct 26 11:51:59 2000 Corinna Vinschen <corinna@vinschen.de>
* dtable.cc (dtable::release): Check for socket. Change
cnt_need_fixup_before accordingly.
(dtable::dup2): Ditto.
(dtable::fixup_before_fork): New method.
(dtable::fixup_before_exec): Ditto.
* dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add
definition for methods `dec_need_fixup_before', `inc_need_fixup_before',
`need_fixup_before', `fixup_before_exec' and `fixup_before_fork'.
* fhandler.h (class fhandler_base): Slight rearrangements. Add
definitions for methods `fixup_before_fork_exec'.
(class fhandler_socket): Eliminate superfluous constructor.
Add member `prot_info_ptr'. Add destructor. Add definitions for
methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and
`fixup_after_exec'.
* fork.cc (fork_parent): Care for file types which need a fixup
before fork. Start child in suspended state then.
* net.cc: New global variable `ws2_32_handle' and `wsadata'.
(fdsock): Check for Winsock version. Call `set_socket_inheritance'
only if Winsock version < 2.0. Care for `need_fixup' count in fdtab.
(cygwin_socket): Eliminate call to `set_socket_inheritance'.
(cygwin_accept): Ditto.
(cygwin_rcmd): Ditto.
(cygwin_rresvport): Ditto.
(cygwin_rexec): Ditto.
(socketpair): Ditto.
(fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate
space for the WSAPROTOCOL_INFOA struct used in fixup.
(fhandler_socket::~fhandler_socket): New destructor.
(fhandler_socket::fixup_before_fork_exec): New method.
(fhandler_socket::fixup_after_fork): Ditto.
(fhandler_socket::dup): Ditto.
(wsock_init): New static function.
(LoadDLLinitfunc (wsock32)): Rearranged.
(LoadDLLinitfunc (ws2_32)): New function.
(dummy_autoload): Add autoload statemants for `WSADuplicateSocketA'
and `WSASocketA'.
* spawn.cc (spawn_guts): Care for file types which need a fixup
before exec. Start child in suspended state then.
Wed Oct 25 20:49:59 2000 Christopher Faylor <cgf@cygnus.com>
* signal.cc (kill_pgrp): Don't limit sending of signals to stopped

View File

@ -153,6 +153,8 @@ dtable::release (int fd)
{
if (!not_open (fd))
{
if ((fds[fd]->get_device () & FH_DEVMASK) == FH_SOCKET)
dec_need_fixup_before ();
delete fds[fd];
fds[fd] = NULL;
}
@ -377,6 +379,11 @@ dtable::dup2 (int oldfd, int newfd)
if (!not_open (newfd))
_close (newfd);
fds[newfd] = newfh;
/* Count sockets. */
if ((fds[newfd]->get_device () & FH_DEVMASK) == FH_SOCKET)
inc_need_fixup_before ();
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
MALLOC_CHECK;
@ -443,6 +450,34 @@ dtable::select_except (int fd, select_record *s)
/* Function to walk the fd table after an exec and perform
per-fhandler type fixups. */
void
dtable::fixup_before_fork (DWORD target_proc_id)
{
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
fhandler_base *fh;
for (size_t i = 0; i < size; i++)
if ((fh = fds[i]) != NULL)
{
debug_printf ("fd %d(%s)", i, fh->get_name ());
fh->fixup_before_fork_exec (target_proc_id);
}
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
}
void
dtable::fixup_before_exec (DWORD target_proc_id)
{
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
fhandler_base *fh;
for (size_t i = 0; i < size; i++)
if ((fh = fds[i]) != NULL && (!fh->get_close_on_exec ()))
{
debug_printf ("fd %d(%s)", i, fh->get_name ());
fh->fixup_before_fork_exec (target_proc_id);
}
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
}
void
dtable::fixup_after_exec (HANDLE parent, size_t sz, fhandler_base **f)
{

View File

@ -16,13 +16,26 @@ class dtable
fhandler_base **fds;
fhandler_base **fds_on_hold;
int first_fd_for_open;
int cnt_need_fixup_before;
public:
size_t size;
dtable () {first_fd_for_open = 3;}
dtable ()
: first_fd_for_open(3), cnt_need_fixup_before(0) {}
void dec_need_fixup_before ()
{ if (cnt_need_fixup_before > 0) --cnt_need_fixup_before; }
void inc_need_fixup_before ()
{ ++cnt_need_fixup_before; }
BOOL need_fixup_before ()
{ return cnt_need_fixup_before > 0; }
int vfork_child_dup ();
void vfork_parent_restore ();
fhandler_base *dup_worker (fhandler_base *oldfh);
int extend (int howmuch);
void fixup_before_exec (DWORD win_proc_id);
void fixup_before_fork (DWORD win_proc_id);
void fixup_after_fork (HANDLE);
fhandler_base *build_fhandler (int fd, DWORD dev, const char *name,
int unit = -1);

View File

@ -197,7 +197,10 @@ public:
void set_need_fork_fixup () { FHSETF (FFIXUP); }
virtual void set_close_on_exec (int val);
virtual void fixup_after_fork (HANDLE parent);
virtual void fixup_before_fork_exec (DWORD) {}
virtual void fixup_after_fork (HANDLE);
virtual void fixup_after_exec (HANDLE) {}
int get_symlink_p () { return FHISSETF (SYMLINK); }
void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); }
@ -291,8 +294,6 @@ public:
virtual int raw_read (void *ptr, size_t ulen);
virtual int raw_write (const void *ptr, size_t ulen);
virtual void fixup_after_exec (HANDLE) {}
/* Virtual accessor functions to hide the fact
that some fd's have two handles. */
virtual HANDLE get_handle () const { return io_handle; }
@ -320,9 +321,11 @@ class fhandler_socket: public fhandler_base
{
private:
int addr_family;
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
public:
fhandler_socket (const char *name = 0);
fhandler_socket (unsigned int, const char *name = 0);
~fhandler_socket ();
int get_socket () const { return (int) get_handle(); }
fhandler_socket * is_socket () { return this; }
int write (const void *ptr, size_t len);
@ -332,6 +335,11 @@ public:
off_t lseek (off_t, int) { return 0; }
int close ();
void hclose (HANDLE) {close ();}
int dup (fhandler_base *child);
virtual void fixup_before_fork_exec (DWORD);
void fixup_after_fork (HANDLE);
void fixup_after_exec (HANDLE parent) { fixup_after_fork (parent); }
select_record *select_read (select_record *s);
select_record *select_write (select_record *s);

View File

@ -341,6 +341,13 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
else
c_flags |= DETACHED_PROCESS;
/* Some file types (currently only sockets) need extra effort in the
parent after CreateProcess and before copying the datastructures
to the child. So we have to start the child in suspend state,
unfortunately, to avoid a race condition. */
if (fdtab.need_fixup_before ())
c_flags |= CREATE_SUSPENDED;
hParent = NULL;
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
DUPLICATE_SAME_ACCESS))
@ -429,6 +436,14 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
return -1;
}
/* Fixup the parent datastructure if needed and resume the child's
main thread. */
if (fdtab.need_fixup_before ())
{
fdtab.fixup_before_fork (pi.dwProcessId);
ResumeThread (pi.hThread);
}
pinfo forked (cygwin_pid (pi.dwProcessId), 1);
/* Initialize things that are done later in dll_crt0_1 that aren't done

View File

@ -22,7 +22,8 @@ details. */
#include <netdb.h>
#include <fcntl.h>
#include "autoload.h"
#include <winsock.h>
#include <winsock2.h>
#include "cygheap.h"
#include "cygerrno.h"
#include "fhandler.h"
#include "path.h"
@ -43,6 +44,9 @@ int __stdcall rresvport (int *);
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
extern HANDLE ws2_32_handle;
WSADATA wsadata;
/* Cygwin internal */
static SOCKET __stdcall
set_socket_inheritance (SOCKET sock)
@ -308,9 +312,12 @@ cygwin_getprotobynumber (int number)
fhandler_socket *
fdsock (int fd, const char *name, SOCKET soc)
{
if (wsadata.wVersion < 512) /* < Winsock 2.0 */
soc = set_socket_inheritance (soc);
fhandler_socket *fh = (fhandler_socket *) fdtab.build_fhandler (fd, FH_SOCKET, name);
fh->set_io_handle ((HANDLE) soc);
fh->set_flags (O_RDWR);
fdtab.inc_need_fixup_before ();
return fh;
}
@ -339,8 +346,6 @@ cygwin_socket (int af, int type, int protocol)
goto done;
}
soc = set_socket_inheritance (soc);
const char *name;
if (af == AF_INET)
name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
@ -720,8 +725,6 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len)
set_winsock_errno ();
else
{
res = set_socket_inheritance (res);
fdsock (res_fd, sock->get_name (), res);
res = res_fd;
}
@ -1593,15 +1596,11 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
goto done;
else
{
res = set_socket_inheritance (res);
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
if (fd2p)
{
fd2s = set_socket_inheritance (fd2s);
fdsock (*fd2p, "/dev/tcp", fd2s);
}
done:
@ -1625,8 +1624,6 @@ cygwin_rresvport (int *port)
goto done;
else
{
res = set_socket_inheritance (res);
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
@ -1658,8 +1655,6 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
goto done;
else
{
res = set_socket_inheritance (res);
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
@ -1766,11 +1761,8 @@ socketpair (int, int type, int, int *sb)
closesocket (newsock);
res = 0;
insock = set_socket_inheritance (insock);
fdsock (sb[0], "/dev/tcp", insock);
outsock = set_socket_inheritance (outsock);
fdsock (sb[1], "/dev/tcp", outsock);
done:
@ -1779,15 +1771,6 @@ done:
return res;
}
/**********************************************************************/
/* fhandler_socket */
fhandler_socket::fhandler_socket (const char *name) :
fhandler_base (FH_SOCKET, name)
{
set_cb (sizeof *this);
}
/* sethostent: standards? */
extern "C" void
sethostent (int)
@ -1800,6 +1783,89 @@ endhostent (void)
{
}
/**********************************************************************/
/* fhandler_socket */
fhandler_socket::fhandler_socket (const char *name) :
fhandler_base (FH_SOCKET, name)
{
set_cb (sizeof *this);
set_need_fork_fixup ();
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
sizeof (WSAPROTOCOL_INFOA));
}
fhandler_socket::~fhandler_socket ()
{
if (prot_info_ptr)
cfree (prot_info_ptr);
}
void
fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
{
int ret = 1;
if (prot_info_ptr &&
(ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr)))
{
debug_printf ("WSADuplicateSocket error");
set_winsock_errno ();
}
if (!ret && ws2_32_handle)
{
debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d",
prot_info_ptr->dwServiceFlags1);
}
else
{
fhandler_base::fixup_before_fork_exec (win_proc_id);
debug_printf ("Without Winsock 2.0");
}
}
void
fhandler_socket::fixup_after_fork (HANDLE parent)
{
SOCKET new_sock = INVALID_SOCKET;
debug_printf ("WSASocket begin, dwServiceFlags1=%d",
prot_info_ptr->dwServiceFlags1);
if (prot_info_ptr &&
(new_sock = WSASocketA (FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
prot_info_ptr, 0, 0)) == INVALID_SOCKET)
{
debug_printf ("WSASocket error");
set_winsock_errno ();
}
if (new_sock != INVALID_SOCKET && ws2_32_handle)
{
debug_printf ("WSASocket went fine");
set_io_handle ((HANDLE) new_sock);
}
else
{
fhandler_base::fixup_after_fork (parent);
debug_printf ("Without Winsock 2.0");
}
}
int
fhandler_socket::dup (fhandler_base *child)
{
fhandler_socket *fhs = (fhandler_socket *) child;
fhs->set_io_handle (get_io_handle ());
fhs->fixup_before_fork_exec (GetCurrentProcessId ());
if (ws2_32_handle)
{
fhs->fixup_after_fork (hMainProc);
return 0;
}
return fhandler_base::dup (child);
}
int
fhandler_socket::read (void *ptr, size_t len)
{
@ -2011,12 +2077,28 @@ fhandler_socket::fcntl (int cmd, void *arg)
return res;
}
static void
wsock_init ()
{
int res = WSAStartup ((2<<8) | 2, &wsadata);
debug_printf ("res %d", res);
debug_printf ("wVersion %d", wsadata.wVersion);
debug_printf ("wHighVersion %d", wsadata.wHighVersion);
debug_printf ("szDescription %s", wsadata.szDescription);
debug_printf ("szSystemStatus %s", wsadata.szSystemStatus);
debug_printf ("iMaxSockets %d", wsadata.iMaxSockets);
debug_printf ("iMaxUdpDg %d", wsadata.iMaxUdpDg);
debug_printf ("lpVendorInfo %d", wsadata.lpVendorInfo);
if (FIONBIO != REAL_FIONBIO)
debug_printf ("**************** FIONBIO != REAL_FIONBIO");
}
extern "C" {
/* Initialize WinSock */
LoadDLLinitfunc (wsock32)
{
WSADATA p;
int res;
HANDLE h;
if ((h = LoadLibrary ("wsock32.dll")) != NULL)
@ -2026,29 +2108,32 @@ LoadDLLinitfunc (wsock32)
else
return 0; /* Already done by another thread? */
res = WSAStartup ((2<<8) | 2, &p);
debug_printf ("res %d", res);
debug_printf ("wVersion %d", p.wVersion);
debug_printf ("wHighVersion %d", p.wHighVersion);
debug_printf ("szDescription %s", p.szDescription);
debug_printf ("szSystemStatus %s", p.szSystemStatus);
debug_printf ("iMaxSockets %d", p.iMaxSockets);
debug_printf ("iMaxUdpDg %d", p.iMaxUdpDg);
debug_printf ("lpVendorInfo %d", p.lpVendorInfo);
if (FIONBIO != REAL_FIONBIO)
debug_printf ("**************** FIONBIO != REAL_FIONBIO");
if (!ws2_32_handle)
wsock_init ();
return 0;
}
LoadDLLinit (wsock32)
/* Initialize WinSock2.0 */
LoadDLLinitfunc (ws2_32)
{
HANDLE h;
if ((h = LoadLibrary ("ws2_32.dll")) == NULL)
return 0; /* Already done or not available. */
ws2_32_handle = h;
if (!wsock32_handle)
wsock_init ();
return 0;
}
static void dummy_autoload (void) __attribute__ ((unused));
static void
dummy_autoload (void)
{
LoadDLLinit (wsock32)
LoadDLLfunc (WSAAsyncSelect, 16, wsock32)
LoadDLLfunc (WSACleanup, 0, wsock32)
LoadDLLfunc (WSAGetLastError, 0, wsock32)
@ -2084,5 +2169,9 @@ LoadDLLfunc (sendto, 24, wsock32)
LoadDLLfunc (setsockopt, 20, wsock32)
LoadDLLfunc (shutdown, 8, wsock32)
LoadDLLfunc (socket, 12, wsock32)
LoadDLLinit (ws2_32)
LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1)
LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
}
}

View File

@ -540,6 +540,14 @@ skip_arg_parsing:
if (mode != _P_OVERLAY)
flags |= CREATE_SUSPENDED;
/* Some file types (currently only sockets) need extra effort in the
parent after CreateProcess and before copying the datastructures
to the child. So we have to start the child in suspend state,
unfortunately, to avoid a race condition. */
if (fdtab.need_fixup_before ())
flags |= CREATE_SUSPENDED;
/* Build windows style environment list */
char *envblock;
if (real_path.iscygexec ())
@ -656,6 +664,15 @@ skip_arg_parsing:
return -1;
}
/* Fixup the parent datastructure if needed and resume the child's
main thread. */
if (fdtab.need_fixup_before ())
{
fdtab.fixup_before_exec (pi.dwProcessId);
if (mode == _P_OVERLAY)
ResumeThread (pi.hThread);
}
if (mode == _P_OVERLAY)
cygpid = myself->pid;
else