Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
15a0f0e7
Commit
15a0f0e7
authored
Jul 03, 2002
by
Martin Wilck
Committed by
Alexandre Julliard
Jul 03, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Check POLLHUP semantics at remote shutdown when wineserver is started.
Fix socket state handling and event handling for non-STREAM sockets.
parent
44e97f02
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
10 deletions
+90
-10
main.c
server/main.c
+1
-0
object.h
server/object.h
+4
-0
sock.c
server/sock.c
+85
-10
No files found.
server/main.c
View file @
15a0f0e7
...
...
@@ -111,6 +111,7 @@ int main( int argc, char *argv[] )
{
parse_args
(
argc
,
argv
);
signal_init
();
sock_init
();
open_master_socket
();
setvbuf
(
stderr
,
NULL
,
_IOLBF
,
0
);
...
...
server/object.h
View file @
15a0f0e7
...
...
@@ -172,6 +172,10 @@ extern void file_set_error(void);
int
get_serial_async_timeout
(
struct
object
*
obj
,
int
type
,
int
count
);
/* socket functions */
extern
void
sock_init
(
void
);
/* debugger functions */
extern
int
set_process_debugger
(
struct
process
*
process
,
struct
thread
*
debugger
);
...
...
server/sock.c
View file @
15a0f0e7
...
...
@@ -67,6 +67,8 @@ struct sock
unsigned
int
hmask
;
/* held (blocked) events */
unsigned
int
pmask
;
/* pending events */
unsigned
int
flags
;
/* socket flags */
unsigned
short
type
;
/* socket type */
unsigned
short
family
;
/* socket family */
struct
event
*
event
;
/* event object */
user_handle_t
window
;
/* window to send the message to */
unsigned
int
message
;
/* message to send */
...
...
@@ -124,6 +126,62 @@ static const int event_bitorder[FD_MAX_EVENTS] =
6
,
7
,
8
,
9
/* leftovers */
};
/* Flags that make sense only for SOCK_STREAM sockets */
#define STREAM_FLAG_MASK ((unsigned int) (FD_CONNECT | FD_ACCEPT | FD_WINE_LISTENING | FD_WINE_CONNECTED))
typedef
enum
{
SOCK_SHUTDOWN_ERROR
=
-
1
,
SOCK_SHUTDOWN_EOF
=
0
,
SOCK_SHUTDOWN_POLLHUP
=
1
}
sock_shutdown_t
;
static
sock_shutdown_t
sock_shutdown_type
=
SOCK_SHUTDOWN_ERROR
;
static
sock_shutdown_t
sock_check_pollhup
(
void
)
{
sock_shutdown_t
ret
=
SOCK_SHUTDOWN_ERROR
;
int
fd
[
2
],
n
;
struct
pollfd
pfd
;
char
dummy
;
if
(
socketpair
(
AF_UNIX
,
SOCK_STREAM
,
0
,
fd
)
)
goto
out
;
if
(
shutdown
(
fd
[
0
],
1
)
)
goto
out
;
pfd
.
fd
=
fd
[
1
];
pfd
.
events
=
POLLIN
;
pfd
.
revents
=
0
;
n
=
poll
(
&
pfd
,
1
,
0
);
if
(
n
!=
1
)
goto
out
;
/* error or timeout */
if
(
pfd
.
revents
&
POLLHUP
)
ret
=
SOCK_SHUTDOWN_POLLHUP
;
else
if
(
pfd
.
revents
&
POLLIN
&&
read
(
fd
[
1
],
&
dummy
,
1
)
==
0
)
ret
=
SOCK_SHUTDOWN_EOF
;
out:
close
(
fd
[
0
]
);
close
(
fd
[
1
]
);
return
ret
;
}
void
sock_init
(
void
)
{
sock_shutdown_type
=
sock_check_pollhup
();
switch
(
sock_shutdown_type
)
{
case
SOCK_SHUTDOWN_EOF
:
if
(
debug_level
)
fprintf
(
stderr
,
"sock_init: shutdown() causes EOF
\n
"
);
break
;
case
SOCK_SHUTDOWN_POLLHUP
:
if
(
debug_level
)
fprintf
(
stderr
,
"sock_init: shutdown() causes POLLHUP
\n
"
);
break
;
default:
fprintf
(
stderr
,
"sock_init: ERROR in sock_check_pollhup()
\n
"
);
sock_shutdown_type
=
SOCK_SHUTDOWN_EOF
;
}
}
static
int
sock_reselect
(
struct
sock
*
sock
)
{
...
...
@@ -222,7 +280,7 @@ inline static int sock_error(int s)
static
void
sock_poll_event
(
struct
object
*
obj
,
int
event
)
{
struct
sock
*
sock
=
(
struct
sock
*
)
obj
;
int
empty_recv
=
0
;
int
hangup_seen
=
0
;
assert
(
sock
->
obj
.
ops
==
&
sock_ops
);
if
(
debug_level
)
...
...
@@ -270,7 +328,7 @@ static void sock_poll_event( struct object *obj, int event )
}
else
{
/* normal data flow */
if
(
event
&
POLLIN
)
if
(
sock
->
type
==
SOCK_STREAM
&&
(
event
&
POLLIN
)
)
{
char
dummy
;
int
nr
;
...
...
@@ -288,7 +346,7 @@ static void sock_poll_event( struct object *obj, int event )
fprintf
(
stderr
,
"socket %d is readable
\n
"
,
sock
->
obj
.
fd
);
}
else
if
(
nr
==
0
)
empty_recv
=
1
;
hangup_seen
=
1
;
else
{
/* EAGAIN can happen if an async recv() falls between the server's poll()
...
...
@@ -304,7 +362,19 @@ static void sock_poll_event( struct object *obj, int event )
}
}
else
if
(
event
&
POLLHUP
)
empty_recv
=
1
;
else
if
(
sock_shutdown_type
==
SOCK_SHUTDOWN_POLLHUP
&&
(
event
&
POLLHUP
)
)
{
hangup_seen
=
1
;
}
else
if
(
event
&
POLLIN
)
/* POLLIN for non-stream socket */
{
sock
->
pmask
|=
FD_READ
;
sock
->
hmask
|=
(
FD_READ
|
FD_CLOSE
);
sock
->
errors
[
FD_READ_BIT
]
=
0
;
if
(
debug_level
)
fprintf
(
stderr
,
"socket %d is readable
\n
"
,
sock
->
obj
.
fd
);
}
if
(
event
&
POLLOUT
)
{
...
...
@@ -323,12 +393,12 @@ static void sock_poll_event( struct object *obj, int event )
fprintf
(
stderr
,
"socket %d got OOB data
\n
"
,
sock
->
obj
.
fd
);
}
/* According to WS2 specs, FD_CLOSE is only delivered when there is
no more data to be read (i.e.
empty_recv
= 1) */
else
if
(
empty_recv
&&
(
sock
->
state
&
(
FD_READ
|
FD_WRITE
)
))
no more data to be read (i.e.
hangup_seen
= 1) */
else
if
(
hangup_seen
&&
(
sock
->
state
&
(
FD_READ
|
FD_WRITE
)
))
{
sock
->
errors
[
FD_CLOSE_BIT
]
=
sock_error
(
sock
->
obj
.
fd
);
if
(
event
&
POLLERR
)
sock
->
state
&=
~
(
FD_WINE_CONNECTED
|
FD_WRITE
);
if
(
(
event
&
POLLERR
)
||
(
sock_shutdown_type
==
SOCK_SHUTDOWN_EOF
&&
(
event
&
POLLHUP
)
)
)
sock
->
state
&=
~
(
FD_WINE_CONNECTED
|
FD_WRITE
);
sock
->
pmask
|=
FD_CLOSE
;
sock
->
hmask
|=
FD_CLOSE
;
if
(
debug_level
)
...
...
@@ -390,8 +460,8 @@ static int sock_get_poll_events( struct object *obj )
ev
|=
POLLIN
|
POLLPRI
;
if
(
mask
&
FD_WRITE
||
(
sock
->
flags
&
WSA_FLAG_OVERLAPPED
&&
IS_READY
(
sock
->
write_q
)))
ev
|=
POLLOUT
;
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication. */
if
(
sock
->
mask
&
~
sock
->
hmask
&
FD_CLOSE
)
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication
for stream sockets
. */
if
(
sock
->
type
==
SOCK_STREAM
&&
(
sock
->
mask
&
~
sock
->
hmask
&
FD_CLOSE
)
)
ev
|=
POLLIN
;
return
ev
;
...
...
@@ -526,6 +596,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
sock
->
hmask
=
0
;
sock
->
pmask
=
0
;
sock
->
flags
=
flags
;
sock
->
type
=
type
;
sock
->
family
=
family
;
sock
->
event
=
NULL
;
sock
->
window
=
0
;
sock
->
message
=
0
;
...
...
@@ -586,6 +658,8 @@ static struct sock *accept_socket( obj_handle_t handle )
acceptsock
->
mask
=
sock
->
mask
;
acceptsock
->
hmask
=
0
;
acceptsock
->
pmask
=
0
;
acceptsock
->
type
=
sock
->
type
;
acceptsock
->
family
=
sock
->
family
;
acceptsock
->
event
=
NULL
;
acceptsock
->
window
=
sock
->
window
;
acceptsock
->
message
=
sock
->
message
;
...
...
@@ -794,6 +868,7 @@ DECL_HANDLER(enable_socket_event)
sock
->
hmask
&=
~
FD_CLOSE
;
sock
->
state
|=
req
->
sstate
;
sock
->
state
&=
~
req
->
cstate
;
if
(
sock
->
type
!=
SOCK_STREAM
)
sock
->
state
&=
~
STREAM_FLAG_MASK
;
pollev
=
sock_reselect
(
sock
);
if
(
pollev
)
sock_try_event
(
sock
,
pollev
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment