Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
f5242405
Commit
f5242405
authored
Feb 28, 2001
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New mechanism to transfer file descriptors from client to server.
parent
0ba59090
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
294 additions
and
144 deletions
+294
-144
file.c
files/file.c
+5
-1
server.h
include/server.h
+9
-3
client.c
scheduler/client.c
+58
-49
file.c
server/file.c
+15
-9
process.c
server/process.c
+15
-8
process.h
server/process.h
+1
-0
request.c
server/request.c
+46
-23
request.h
server/request.h
+1
-1
thread.c
server/thread.c
+129
-44
thread.h
server/thread.h
+11
-1
trace.c
server/trace.c
+4
-5
No files found.
files/file.c
View file @
f5242405
...
...
@@ -184,10 +184,14 @@ void FILE_SetDosError(void)
HANDLE
FILE_DupUnixHandle
(
int
fd
,
DWORD
access
)
{
HANDLE
ret
;
wine_server_send_fd
(
fd
);
SERVER_START_REQ
(
alloc_file_handle
)
{
req
->
access
=
access
;
SERVER_CALL_FD
(
fd
);
req
->
fd
=
fd
;
SERVER_CALL
();
ret
=
req
->
handle
;
}
SERVER_END_REQ
;
...
...
include/server.h
View file @
f5242405
...
...
@@ -118,6 +118,12 @@ typedef struct
union
debug_event_data
info
;
/* event information */
}
debug_event_t
;
/* structure used in sending an fd from client to server */
struct
send_fd
{
void
*
tid
;
/* thread id */
int
fd
;
/* file descriptor on client-side */
};
/* Create a new process from the context of the parent */
struct
new_process_request
...
...
@@ -539,6 +545,7 @@ struct alloc_file_handle_request
{
REQUEST_HEADER
;
/* request header */
IN
unsigned
int
access
;
/* wanted access rights */
IN
int
fd
;
/* file descriptor on the client side */
OUT
handle_t
handle
;
/* handle to the file */
};
...
...
@@ -1592,7 +1599,7 @@ union generic_request
struct
async_result_request
async_result
;
};
#define SERVER_PROTOCOL_VERSION
39
#define SERVER_PROTOCOL_VERSION
40
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
@@ -1611,10 +1618,10 @@ union generic_request
/* client communication functions */
extern
unsigned
int
wine_server_call
(
union
generic_request
*
req
,
size_t
size
);
extern
unsigned
int
wine_server_call_fd
(
union
generic_request
*
req
,
size_t
size
,
int
fd
);
extern
void
server_protocol_error
(
const
char
*
err
,
...
)
WINE_NORETURN
;
extern
void
server_protocol_perror
(
const
char
*
err
)
WINE_NORETURN
;
extern
void
wine_server_alloc_req
(
union
generic_request
*
req
,
size_t
size
);
extern
void
wine_server_send_fd
(
int
fd
);
extern
int
wine_server_recv_fd
(
int
handle
,
int
cache
);
extern
const
char
*
get_config_dir
(
void
);
...
...
@@ -1685,7 +1692,6 @@ struct __server_exception_frame
#define SERVER_CALL() (wine_server_call( &__req, sizeof(*req) ))
#define SERVER_CALL_ERR() (__server_call_err( &__req, sizeof(*req) ))
#define SERVER_CALL_FD(fd) (wine_server_call_fd( &__req, sizeof(*req), (fd) ))
extern
int
CLIENT_InitServer
(
void
);
...
...
scheduler/client.c
View file @
f5242405
...
...
@@ -55,7 +55,8 @@ struct cmsg_fd
};
static
void
*
boot_thread_id
;
static
sigset_t
block_set
;
/* signals to block during server calls */
static
int
fd_socket
;
/* socket to exchange file descriptors with the server */
/* die on a fatal error; use only during initialization */
static
void
fatal_error
(
const
char
*
err
,
...
)
WINE_NORETURN
;
...
...
@@ -159,47 +160,6 @@ static void send_request( union generic_request *request )
}
/***********************************************************************
* send_request_fd
*
* Send a request to the server, passing a file descriptor.
*/
static
void
send_request_fd
(
union
generic_request
*
request
,
int
fd
)
{
#ifndef HAVE_MSGHDR_ACCRIGHTS
struct
cmsg_fd
cmsg
;
#endif
struct
msghdr
msghdr
;
struct
iovec
vec
;
int
ret
;
vec
.
iov_base
=
(
void
*
)
request
;
vec
.
iov_len
=
sizeof
(
*
request
);
msghdr
.
msg_name
=
NULL
;
msghdr
.
msg_namelen
=
0
;
msghdr
.
msg_iov
=
&
vec
;
msghdr
.
msg_iovlen
=
1
;
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr
.
msg_accrights
=
(
void
*
)
&
fd
;
msghdr
.
msg_accrightslen
=
sizeof
(
fd
);
#else
/* HAVE_MSGHDR_ACCRIGHTS */
cmsg
.
len
=
sizeof
(
cmsg
);
cmsg
.
level
=
SOL_SOCKET
;
cmsg
.
type
=
SCM_RIGHTS
;
cmsg
.
fd
=
fd
;
msghdr
.
msg_control
=
&
cmsg
;
msghdr
.
msg_controllen
=
sizeof
(
cmsg
);
msghdr
.
msg_flags
=
0
;
#endif
/* HAVE_MSGHDR_ACCRIGHTS */
if
((
ret
=
sendmsg
(
NtCurrentTeb
()
->
socket
,
&
msghdr
,
0
))
==
sizeof
(
*
request
))
return
;
if
(
ret
>=
0
)
server_protocol_error
(
"partial write %d
\n
"
,
ret
);
if
(
errno
==
EPIPE
)
SYSDEPS_ExitThread
(
0
);
server_protocol_perror
(
"sendmsg"
);
}
/***********************************************************************
* wait_reply
*
* Wait for a reply from the server.
...
...
@@ -230,24 +190,64 @@ static void wait_reply( union generic_request *req )
*/
unsigned
int
wine_server_call
(
union
generic_request
*
req
,
size_t
size
)
{
sigset_t
old_set
;
memset
(
(
char
*
)
req
+
size
,
0
,
sizeof
(
*
req
)
-
size
);
sigprocmask
(
SIG_BLOCK
,
&
block_set
,
&
old_set
);
send_request
(
req
);
wait_reply
(
req
);
sigprocmask
(
SIG_SETMASK
,
&
old_set
,
NULL
);
return
req
->
header
.
error
;
}
/***********************************************************************
* wine_server_
call
_fd
* wine_server_
send
_fd
*
*
Perform a server call, passing a file descripto
r.
*
Send a file descriptor to the serve
r.
*/
unsigned
int
wine_server_call_fd
(
union
generic_request
*
req
,
size_t
size
,
int
fd
)
void
wine_server_send_fd
(
int
fd
)
{
memset
(
(
char
*
)
req
+
size
,
0
,
sizeof
(
*
req
)
-
size
);
send_request_fd
(
req
,
fd
);
wait_reply
(
req
);
return
req
->
header
.
error
;
#ifndef HAVE_MSGHDR_ACCRIGHTS
struct
cmsg_fd
cmsg
;
#endif
struct
send_fd
data
;
struct
msghdr
msghdr
;
struct
iovec
vec
;
int
ret
;
vec
.
iov_base
=
(
void
*
)
&
data
;
vec
.
iov_len
=
sizeof
(
data
);
msghdr
.
msg_name
=
NULL
;
msghdr
.
msg_namelen
=
0
;
msghdr
.
msg_iov
=
&
vec
;
msghdr
.
msg_iovlen
=
1
;
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr
.
msg_accrights
=
(
void
*
)
&
fd
;
msghdr
.
msg_accrightslen
=
sizeof
(
fd
);
#else
/* HAVE_MSGHDR_ACCRIGHTS */
cmsg
.
len
=
sizeof
(
cmsg
);
cmsg
.
level
=
SOL_SOCKET
;
cmsg
.
type
=
SCM_RIGHTS
;
cmsg
.
fd
=
fd
;
msghdr
.
msg_control
=
&
cmsg
;
msghdr
.
msg_controllen
=
sizeof
(
cmsg
);
msghdr
.
msg_flags
=
0
;
#endif
/* HAVE_MSGHDR_ACCRIGHTS */
data
.
tid
=
(
void
*
)
GetCurrentThreadId
();
data
.
fd
=
fd
;
for
(;;)
{
if
((
ret
=
sendmsg
(
fd_socket
,
&
msghdr
,
0
))
==
sizeof
(
data
))
return
;
if
(
ret
>=
0
)
server_protocol_error
(
"partial write %d
\n
"
,
ret
);
if
(
errno
==
EINTR
)
continue
;
if
(
errno
==
EPIPE
)
SYSDEPS_ExitThread
(
0
);
server_protocol_perror
(
"sendmsg"
);
}
}
...
...
@@ -563,6 +563,7 @@ int CLIENT_InitServer(void)
/* connect to the server */
fd
=
server_connect
(
oldcwd
,
serverdir
);
fd_socket
=
dup
(
fd
);
/* switch back to the starting directory */
if
(
oldcwd
)
...
...
@@ -570,6 +571,14 @@ int CLIENT_InitServer(void)
chdir
(
oldcwd
);
free
(
oldcwd
);
}
/* setup the signal mask */
sigemptyset
(
&
block_set
);
sigaddset
(
&
block_set
,
SIGALRM
);
sigaddset
(
&
block_set
,
SIGIO
);
sigaddset
(
&
block_set
,
SIGINT
);
sigaddset
(
&
block_set
,
SIGHUP
);
return
fd
;
}
...
...
server/file.c
View file @
f5242405
...
...
@@ -403,6 +403,12 @@ static int set_file_time( handle_t handle, time_t access_time, time_t write_time
if
(
!
(
file
=
get_file_obj
(
current
->
process
,
handle
,
GENERIC_WRITE
)))
return
0
;
if
(
!
file
->
name
)
{
set_error
(
STATUS_INVALID_HANDLE
);
release_object
(
file
);
return
0
;
}
if
(
!
access_time
||
!
write_time
)
{
struct
stat
st
;
...
...
@@ -453,19 +459,19 @@ DECL_HANDLER(create_file)
DECL_HANDLER
(
alloc_file_handle
)
{
struct
file
*
file
;
int
fd
;
req
->
handle
=
0
;
if
(
current
->
pass_fd
!
=
-
1
)
if
(
(
fd
=
thread_get_inflight_fd
(
current
,
req
->
fd
))
=
=
-
1
)
{
if
((
file
=
create_file_for_fd
(
current
->
pass_fd
,
req
->
access
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
0
)))
{
req
->
handle
=
alloc_handle
(
current
->
process
,
file
,
req
->
access
,
0
);
release_object
(
file
);
}
current
->
pass_fd
=
-
1
;
set_error
(
STATUS_INVALID_HANDLE
);
return
;
}
if
((
file
=
create_file_for_fd
(
fd
,
req
->
access
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
0
)))
{
req
->
handle
=
alloc_handle
(
current
->
process
,
file
,
req
->
access
,
0
);
release_object
(
file
)
;
}
else
set_error
(
STATUS_INVALID_PARAMETER
);
}
/* get a Unix fd to access a file */
...
...
server/process.c
View file @
f5242405
...
...
@@ -36,6 +36,7 @@ static int running_processes;
static
void
process_dump
(
struct
object
*
obj
,
int
verbose
);
static
int
process_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
);
static
void
process_poll_event
(
struct
object
*
obj
,
int
event
);
static
void
process_destroy
(
struct
object
*
obj
);
static
const
struct
object_ops
process_ops
=
...
...
@@ -47,7 +48,7 @@ static const struct object_ops process_ops =
process_signaled
,
/* signaled */
no_satisfied
,
/* satisfied */
NULL
,
/* get_poll_events */
NULL
,
/* poll_event */
process_poll_event
,
/* poll_event */
no_get_fd
,
/* get_fd */
no_flush
,
/* flush */
no_get_file_info
,
/* get_file_info */
...
...
@@ -147,11 +148,7 @@ struct thread *create_process( int fd )
struct
process
*
process
;
struct
thread
*
thread
=
NULL
;
if
(
!
(
process
=
alloc_object
(
&
process_ops
,
-
1
)))
{
close
(
fd
);
return
NULL
;
}
if
(
!
(
process
=
alloc_object
(
&
process_ops
,
fd
)))
return
NULL
;
process
->
next
=
NULL
;
process
->
prev
=
NULL
;
process
->
thread_list
=
NULL
;
...
...
@@ -183,8 +180,9 @@ struct thread *create_process( int fd )
if
(
!
(
process
->
init_event
=
create_event
(
NULL
,
0
,
1
,
0
)))
goto
error
;
/* create the main thread */
if
(
!
(
thread
=
create_thread
(
fd
,
process
)))
goto
error
;
if
(
!
(
thread
=
create_thread
(
dup
(
fd
)
,
process
)))
goto
error
;
set_select_events
(
&
process
->
obj
,
POLLIN
);
/* start listening to events */
release_object
(
process
);
return
thread
;
...
...
@@ -311,6 +309,15 @@ static int process_signaled( struct object *obj, struct thread *thread )
}
static
void
process_poll_event
(
struct
object
*
obj
,
int
event
)
{
struct
process
*
process
=
(
struct
process
*
)
obj
;
assert
(
obj
->
ops
==
&
process_ops
);
if
(
event
&
(
POLLERR
|
POLLHUP
))
set_select_events
(
obj
,
-
1
);
else
if
(
event
&
POLLIN
)
receive_fd
(
process
);
}
static
void
startup_info_destroy
(
struct
object
*
obj
)
{
struct
startup_info
*
info
=
(
struct
startup_info
*
)
obj
;
...
...
@@ -491,7 +498,7 @@ void resume_process( struct process *process )
}
/* kill a process on the spot */
static
void
kill_process
(
struct
process
*
process
,
struct
thread
*
skip
,
int
exit_code
)
void
kill_process
(
struct
process
*
process
,
struct
thread
*
skip
,
int
exit_code
)
{
struct
thread
*
thread
=
process
->
thread_list
;
while
(
thread
)
...
...
server/process.h
View file @
f5242405
...
...
@@ -82,6 +82,7 @@ extern void remove_process_thread( struct process *process,
struct
thread
*
thread
);
extern
void
suspend_process
(
struct
process
*
process
);
extern
void
resume_process
(
struct
process
*
process
);
extern
void
kill_process
(
struct
process
*
process
,
struct
thread
*
skip
,
int
exit_code
);
extern
void
kill_debugged_processes
(
struct
thread
*
debugger
,
int
exit_code
);
extern
struct
process_snapshot
*
process_snap
(
int
*
count
);
extern
struct
module_snapshot
*
module_snap
(
struct
process
*
process
,
int
*
count
);
...
...
server/request.c
View file @
f5242405
...
...
@@ -204,8 +204,6 @@ void send_reply( struct thread *thread, union generic_request *request )
{
int
ret
;
assert
(
thread
->
pass_fd
==
-
1
);
if
(
debug_level
)
trace_reply
(
thread
,
request
);
request
->
header
.
error
=
thread
->
error
;
...
...
@@ -221,43 +219,68 @@ void send_reply( struct thread *thread, union generic_request *request )
}
}
/* re
ad a message from a client that has something to say
*/
void
read_request
(
struct
thread
*
thread
)
/* re
ceive a file descriptor on the process socket
*/
int
receive_fd
(
struct
process
*
process
)
{
union
generic_request
req
;
int
ret
;
struct
send_fd
data
;
int
fd
,
ret
;
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr
.
msg_accrightslen
=
sizeof
(
int
);
msghdr
.
msg_accrights
=
(
void
*
)
&
thread
->
pass_
fd
;
msghdr
.
msg_accrights
=
(
void
*
)
&
fd
;
#else
/* HAVE_MSGHDR_ACCRIGHTS */
msghdr
.
msg_control
=
&
cmsg
;
msghdr
.
msg_controllen
=
sizeof
(
cmsg
);
cmsg
.
fd
=
-
1
;
#endif
/* HAVE_MSGHDR_ACCRIGHTS */
assert
(
thread
->
pass_fd
==
-
1
);
myiovec
.
iov_base
=
&
data
;
myiovec
.
iov_len
=
sizeof
(
data
);
myiovec
.
iov_base
=
&
req
;
myiovec
.
iov_len
=
sizeof
(
req
);
ret
=
recvmsg
(
thread
->
obj
.
fd
,
&
msghdr
,
0
);
ret
=
recvmsg
(
process
->
obj
.
fd
,
&
msghdr
,
0
);
#ifndef HAVE_MSGHDR_ACCRIGHTS
thread
->
pass_
fd
=
cmsg
.
fd
;
fd
=
cmsg
.
fd
;
#endif
if
(
ret
==
sizeof
(
req
))
if
(
ret
==
sizeof
(
data
))
{
call_req_handler
(
thread
,
&
req
);
thread
->
pass_fd
=
-
1
;
return
;
struct
thread
*
thread
=
get_thread_from_id
(
data
.
tid
);
if
(
!
thread
||
thread
->
process
!=
process
)
{
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *fd* %d <- %d bad thread id
\n
"
,
(
unsigned
int
)
data
.
tid
,
data
.
fd
,
fd
);
close
(
fd
);
}
else
{
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *fd* %d <- %d
\n
"
,
(
unsigned
int
)
thread
,
data
.
fd
,
fd
);
thread_add_inflight_fd
(
thread
,
data
.
fd
,
fd
);
}
return
0
;
}
if
(
!
ret
)
{
set_select_events
(
&
process
->
obj
,
-
1
);
/* stop waiting on it */
}
if
(
!
ret
)
/* closed pipe */
kill_thread
(
thread
,
0
);
else
if
(
ret
>
0
)
fatal_protocol_error
(
thread
,
"partial recvmsg %d
\n
"
,
ret
);
else
fatal_protocol_perror
(
thread
,
"recvmsg"
);
{
fprintf
(
stderr
,
"Protocol error: process %p: partial recvmsg %d for fd
\n
"
,
process
,
ret
);
kill_process
(
process
,
NULL
,
1
);
}
else
if
(
ret
<
0
)
{
if
(
errno
!=
EWOULDBLOCK
&&
errno
!=
EAGAIN
)
{
fprintf
(
stderr
,
"Protocol error: process %p: "
,
process
);
perror
(
"recvmsg"
);
kill_process
(
process
,
NULL
,
1
);
}
}
return
-
1
;
}
/* send the wakeup signal to a thread */
...
...
@@ -280,7 +303,7 @@ int send_client_fd( struct thread *thread, int fd, handle_t handle )
int
ret
;
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *fd* %d
=
%d
\n
"
,
(
unsigned
int
)
thread
,
handle
,
fd
);
fprintf
(
stderr
,
"%08x: *fd* %d
->
%d
\n
"
,
(
unsigned
int
)
thread
,
handle
,
fd
);
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr
.
msg_accrightslen
=
sizeof
(
fd
);
...
...
server/request.h
View file @
f5242405
...
...
@@ -31,7 +31,7 @@ extern void fatal_protocol_error( struct thread *thread, const char *err, ... );
extern
void
fatal_error
(
const
char
*
err
,
...
)
WINE_NORETURN
;
extern
void
fatal_perror
(
const
char
*
err
,
...
)
WINE_NORETURN
;
extern
const
char
*
get_config_dir
(
void
);
extern
void
read_request
(
struct
thread
*
thread
);
extern
int
receive_fd
(
struct
process
*
process
);
extern
int
send_thread_wakeup
(
struct
thread
*
thread
,
int
signaled
);
extern
int
send_client_fd
(
struct
thread
*
thread
,
int
fd
,
handle_t
handle
);
extern
void
send_reply
(
struct
thread
*
thread
,
union
generic_request
*
request
);
...
...
server/thread.c
View file @
f5242405
...
...
@@ -61,7 +61,7 @@ struct thread_apc
static
void
dump_thread
(
struct
object
*
obj
,
int
verbose
);
static
int
thread_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
);
extern
void
thread_poll_event
(
struct
object
*
obj
,
int
event
);
static
void
thread_poll_event
(
struct
object
*
obj
,
int
event
);
static
void
destroy_thread
(
struct
object
*
obj
);
static
struct
thread_apc
*
thread_dequeue_apc
(
struct
thread
*
thread
,
int
system_only
);
...
...
@@ -139,6 +139,43 @@ static int alloc_client_buffer( struct thread *thread )
return
0
;
}
/* initialize the structure for a newly allocated thread */
inline
static
void
init_thread_structure
(
struct
thread
*
thread
)
{
int
i
;
thread
->
unix_pid
=
0
;
/* not known yet */
thread
->
context
=
NULL
;
thread
->
teb
=
NULL
;
thread
->
mutex
=
NULL
;
thread
->
debug_ctx
=
NULL
;
thread
->
debug_event
=
NULL
;
thread
->
queue
=
NULL
;
thread
->
info
=
NULL
;
thread
->
wait
=
NULL
;
thread
->
system_apc
.
head
=
NULL
;
thread
->
system_apc
.
tail
=
NULL
;
thread
->
user_apc
.
head
=
NULL
;
thread
->
user_apc
.
tail
=
NULL
;
thread
->
error
=
0
;
thread
->
request_fd
=
NULL
;
thread
->
reply_fd
=
-
1
;
thread
->
wait_fd
=
-
1
;
thread
->
state
=
RUNNING
;
thread
->
attached
=
0
;
thread
->
exit_code
=
0
;
thread
->
next
=
NULL
;
thread
->
prev
=
NULL
;
thread
->
priority
=
THREAD_PRIORITY_NORMAL
;
thread
->
affinity
=
1
;
thread
->
suspend
=
0
;
thread
->
buffer
=
(
void
*
)
-
1
;
thread
->
last_req
=
REQ_get_thread_buffer
;
for
(
i
=
0
;
i
<
MAX_INFLIGHT_FDS
;
i
++
)
thread
->
inflight
[
i
].
server
=
thread
->
inflight
[
i
].
client
=
-
1
;
}
/* create a new thread */
struct
thread
*
create_thread
(
int
fd
,
struct
process
*
process
)
{
...
...
@@ -149,36 +186,9 @@ struct thread *create_thread( int fd, struct process *process )
if
(
!
(
thread
=
alloc_object
(
&
thread_ops
,
fd
)))
return
NULL
;
thread
->
unix_pid
=
0
;
/* not known yet */
thread
->
context
=
NULL
;
thread
->
teb
=
NULL
;
thread
->
mutex
=
NULL
;
thread
->
debug_ctx
=
NULL
;
thread
->
debug_event
=
NULL
;
thread
->
queue
=
NULL
;
thread
->
info
=
NULL
;
thread
->
wait
=
NULL
;
thread
->
system_apc
.
head
=
NULL
;
thread
->
system_apc
.
tail
=
NULL
;
thread
->
user_apc
.
head
=
NULL
;
thread
->
user_apc
.
tail
=
NULL
;
thread
->
error
=
0
;
thread
->
pass_fd
=
-
1
;
thread
->
request_fd
=
NULL
;
thread
->
reply_fd
=
-
1
;
thread
->
wait_fd
=
-
1
;
thread
->
state
=
RUNNING
;
thread
->
attached
=
0
;
thread
->
exit_code
=
0
;
thread
->
next
=
NULL
;
thread
->
prev
=
NULL
;
thread
->
priority
=
THREAD_PRIORITY_NORMAL
;
thread
->
affinity
=
1
;
thread
->
suspend
=
0
;
thread
->
buffer
=
(
void
*
)
-
1
;
thread
->
last_req
=
REQ_get_thread_buffer
;
thread
->
process
=
(
struct
process
*
)
grab_object
(
process
);
init_thread_structure
(
thread
);
thread
->
process
=
(
struct
process
*
)
grab_object
(
process
);
if
(
!
current
)
current
=
thread
;
if
(
!
booting_thread
)
/* first thread ever */
...
...
@@ -190,7 +200,9 @@ struct thread *create_thread( int fd, struct process *process )
if
((
thread
->
next
=
first_thread
)
!=
NULL
)
thread
->
next
->
prev
=
thread
;
first_thread
=
thread
;
#if 0
set_select_events( &thread->obj, POLLIN ); /* start listening to events */
#endif
if
(
!
alloc_client_buffer
(
thread
))
goto
error
;
return
thread
;
...
...
@@ -200,13 +212,41 @@ struct thread *create_thread( int fd, struct process *process )
}
/* handle a client event */
void
thread_poll_event
(
struct
object
*
obj
,
int
event
)
static
void
thread_poll_event
(
struct
object
*
obj
,
int
event
)
{
struct
thread
*
thread
=
(
struct
thread
*
)
obj
;
assert
(
obj
->
ops
==
&
thread_ops
);
if
(
event
&
(
POLLERR
|
POLLHUP
))
kill_thread
(
thread
,
0
);
#if 0
else if (event & POLLIN) read_request( thread );
#endif
}
/* cleanup everything that is no longer needed by a dead thread */
/* used by destroy_thread and kill_thread */
static
void
cleanup_thread
(
struct
thread
*
thread
)
{
int
i
;
struct
thread_apc
*
apc
;
while
((
apc
=
thread_dequeue_apc
(
thread
,
0
)))
free
(
apc
);
if
(
thread
->
buffer
!=
(
void
*
)
-
1
)
munmap
(
thread
->
buffer
,
MAX_REQUEST_LENGTH
);
if
(
thread
->
reply_fd
!=
-
1
)
close
(
thread
->
reply_fd
);
if
(
thread
->
wait_fd
!=
-
1
)
close
(
thread
->
wait_fd
);
if
(
thread
->
request_fd
)
release_object
(
thread
->
request_fd
);
for
(
i
=
0
;
i
<
MAX_INFLIGHT_FDS
;
i
++
)
{
if
(
thread
->
inflight
[
i
].
client
!=
-
1
)
{
close
(
thread
->
inflight
[
i
].
server
);
thread
->
inflight
[
i
].
client
=
thread
->
inflight
[
i
].
server
=
-
1
;
}
}
thread
->
buffer
=
(
void
*
)
-
1
;
thread
->
reply_fd
=
-
1
;
thread
->
wait_fd
=
-
1
;
thread
->
request_fd
=
NULL
;
}
/* destroy a thread when its refcount is 0 */
...
...
@@ -224,11 +264,7 @@ static void destroy_thread( struct object *obj )
while
((
apc
=
thread_dequeue_apc
(
thread
,
0
)))
free
(
apc
);
if
(
thread
->
info
)
release_object
(
thread
->
info
);
if
(
thread
->
queue
)
release_object
(
thread
->
queue
);
if
(
thread
->
buffer
!=
(
void
*
)
-
1
)
munmap
(
thread
->
buffer
,
MAX_REQUEST_LENGTH
);
if
(
thread
->
reply_fd
!=
-
1
)
close
(
thread
->
reply_fd
);
if
(
thread
->
wait_fd
!=
-
1
)
close
(
thread
->
wait_fd
);
if
(
thread
->
pass_fd
!=
-
1
)
close
(
thread
->
pass_fd
);
if
(
thread
->
request_fd
)
release_object
(
thread
->
request_fd
);
cleanup_thread
(
thread
);
}
/* dump a thread on stdout for debugging purposes */
...
...
@@ -599,6 +635,62 @@ static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_
return
apc
;
}
/* add an fd to the inflight list */
/* return list index, or -1 on error */
int
thread_add_inflight_fd
(
struct
thread
*
thread
,
int
client
,
int
server
)
{
int
i
;
if
(
server
==
-
1
)
return
-
1
;
if
(
client
==
-
1
)
{
close
(
server
);
return
-
1
;
}
/* first check if we already have an entry for this fd */
for
(
i
=
0
;
i
<
MAX_INFLIGHT_FDS
;
i
++
)
if
(
thread
->
inflight
[
i
].
client
==
client
)
{
close
(
thread
->
inflight
[
i
].
server
);
thread
->
inflight
[
i
].
server
=
server
;
return
i
;
}
/* now find a free spot to store it */
for
(
i
=
0
;
i
<
MAX_INFLIGHT_FDS
;
i
++
)
if
(
thread
->
inflight
[
i
].
client
==
-
1
)
{
thread
->
inflight
[
i
].
client
=
client
;
thread
->
inflight
[
i
].
server
=
server
;
return
i
;
}
return
-
1
;
}
/* get an inflight fd and purge it from the list */
/* the fd must be closed when no longer used */
int
thread_get_inflight_fd
(
struct
thread
*
thread
,
int
client
)
{
int
i
,
ret
;
if
(
client
==
-
1
)
return
-
1
;
do
{
for
(
i
=
0
;
i
<
MAX_INFLIGHT_FDS
;
i
++
)
{
if
(
thread
->
inflight
[
i
].
client
==
client
)
{
ret
=
thread
->
inflight
[
i
].
server
;
thread
->
inflight
[
i
].
server
=
thread
->
inflight
[
i
].
client
=
-
1
;
return
ret
;
}
}
}
while
(
!
receive_fd
(
thread
->
process
));
/* in case it is still in the socket buffer */
return
-
1
;
}
/* retrieve an LDT selector entry */
static
void
get_selector_entry
(
struct
thread
*
thread
,
int
entry
,
unsigned
int
*
base
,
unsigned
int
*
limit
,
...
...
@@ -649,14 +741,7 @@ void kill_thread( struct thread *thread, int violent_death )
wake_up
(
&
thread
->
obj
,
0
);
detach_thread
(
thread
,
violent_death
?
SIGTERM
:
0
);
remove_select_user
(
&
thread
->
obj
);
release_object
(
thread
->
request_fd
);
close
(
thread
->
reply_fd
);
close
(
thread
->
wait_fd
);
munmap
(
thread
->
buffer
,
MAX_REQUEST_LENGTH
);
thread
->
request_fd
=
NULL
;
thread
->
reply_fd
=
-
1
;
thread
->
wait_fd
=
-
1
;
thread
->
buffer
=
(
void
*
)
-
1
;
cleanup_thread
(
thread
);
release_object
(
thread
);
}
...
...
server/thread.h
View file @
f5242405
...
...
@@ -36,6 +36,14 @@ struct apc_queue
struct
thread_apc
*
tail
;
};
/* descriptor for fds currently in flight from client to server */
struct
inflight_fd
{
int
client
;
/* fd on the client side (or -1 if entry is free) */
int
server
;
/* fd on the server side */
};
#define MAX_INFLIGHT_FDS 16
/* max number of fds in flight per thread */
struct
thread
{
struct
object
obj
;
/* object header */
...
...
@@ -52,9 +60,9 @@ struct thread
struct
thread_wait
*
wait
;
/* current wait condition if sleeping */
struct
apc_queue
system_apc
;
/* queue of system async procedure calls */
struct
apc_queue
user_apc
;
/* queue of user async procedure calls */
struct
inflight_fd
inflight
[
MAX_INFLIGHT_FDS
];
/* fds currently in flight */
unsigned
int
error
;
/* current error code */
struct
object
*
request_fd
;
/* fd for receiving client requests */
int
pass_fd
;
/* fd to pass to the client */
int
reply_fd
;
/* fd to send a reply to a client */
int
wait_fd
;
/* fd to use to wake a sleeping client */
enum
run_state
state
;
/* running state */
...
...
@@ -96,6 +104,8 @@ extern void wake_up( struct object *obj, int max );
extern
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
void
*
func
,
enum
apc_type
type
,
int
system
,
int
nb_args
,
...
);
extern
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
int
system
);
extern
int
thread_add_inflight_fd
(
struct
thread
*
thread
,
int
client
,
int
server
);
extern
int
thread_get_inflight_fd
(
struct
thread
*
thread
,
int
client
);
extern
struct
thread_snapshot
*
thread_snap
(
int
*
count
);
/* ptrace functions */
...
...
server/trace.c
View file @
f5242405
...
...
@@ -670,7 +670,8 @@ static void dump_create_file_reply( const struct create_file_request *req )
static
void
dump_alloc_file_handle_request
(
const
struct
alloc_file_handle_request
*
req
)
{
fprintf
(
stderr
,
" access=%08x"
,
req
->
access
);
fprintf
(
stderr
,
" access=%08x,"
,
req
->
access
);
fprintf
(
stderr
,
" fd=%d"
,
req
->
fd
);
}
static
void
dump_alloc_file_handle_reply
(
const
struct
alloc_file_handle_request
*
req
)
...
...
@@ -1889,11 +1890,9 @@ void trace_request( struct thread *thread, const union generic_request *request
fprintf
(
stderr
,
"%08x: %s("
,
(
unsigned
int
)
thread
,
req_names
[
req
]
);
cur_pos
=
0
;
req_dumpers
[
req
](
request
);
fprintf
(
stderr
,
" )
\n
"
);
}
else
fprintf
(
stderr
,
"%08x: %d("
,
(
unsigned
int
)
thread
,
req
);
if
(
thread
->
pass_fd
!=
-
1
)
fprintf
(
stderr
,
" ) fd=%d
\n
"
,
thread
->
pass_fd
);
else
fprintf
(
stderr
,
" )
\n
"
);
else
fprintf
(
stderr
,
"%08x: %d(???)
\n
"
,
(
unsigned
int
)
thread
,
req
);
}
void
trace_reply
(
struct
thread
*
thread
,
const
union
generic_request
*
request
)
...
...
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