Do not set EH_NONCONTINUABLE.
[wine.git] / scheduler / client.c
blob055695264b8fa592b780f22ed4d90103c086d257
1 /*
2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <assert.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #ifdef HAVE_SYS_MMAN_H
17 #include <sys/mman.h>
18 #endif
19 #include <sys/uio.h>
20 #include <unistd.h>
21 #include <stdarg.h>
23 #include "process.h"
24 #include "thread.h"
25 #include "server.h"
26 #include "winerror.h"
28 /* Some versions of glibc don't define this */
29 #ifndef SCM_RIGHTS
30 #define SCM_RIGHTS 1
31 #endif
33 /* data structure used to pass an fd with sendmsg/recvmsg */
34 struct cmsg_fd
36 int len; /* sizeof structure */
37 int level; /* SOL_SOCKET */
38 int type; /* SCM_RIGHTS */
39 int fd; /* fd to pass */
42 /***********************************************************************
43 * CLIENT_Die
45 * Die on protocol errors or socket close
47 static void CLIENT_Die(void)
49 close( NtCurrentTeb()->socket );
50 SYSDEPS_ExitThread();
53 /***********************************************************************
54 * server_protocol_error
56 void server_protocol_error( const char *err, ... )
58 va_list args;
60 va_start( args, err );
61 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
62 vfprintf( stderr, err, args );
63 va_end( args );
64 CLIENT_Die();
68 /***********************************************************************
69 * server_perror
71 static void server_perror( const char *err )
73 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
74 perror( err );
75 CLIENT_Die();
79 /***********************************************************************
80 * send_request
82 * Send a request to the server.
84 static void send_request( enum request req )
86 int ret;
87 if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
88 return;
89 if (ret == -1)
91 if (errno == EPIPE) CLIENT_Die();
92 server_perror( "sendmsg" );
94 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
97 /***********************************************************************
98 * send_request_fd
100 * Send a request to the server, passing a file descriptor.
102 static void send_request_fd( enum request req, int fd )
104 int ret;
105 #ifndef HAVE_MSGHDR_ACCRIGHTS
106 struct cmsg_fd cmsg;
107 #endif
108 struct msghdr msghdr;
109 struct iovec vec;
111 vec.iov_base = (void *)&req;
112 vec.iov_len = sizeof(req);
114 msghdr.msg_name = NULL;
115 msghdr.msg_namelen = 0;
116 msghdr.msg_iov = &vec;
117 msghdr.msg_iovlen = 1;
119 #ifdef HAVE_MSGHDR_ACCRIGHTS
120 msghdr.msg_accrights = (void *)&fd;
121 msghdr.msg_accrightslen = sizeof(fd);
122 #else /* HAVE_MSGHDR_ACCRIGHTS */
123 cmsg.len = sizeof(cmsg);
124 cmsg.level = SOL_SOCKET;
125 cmsg.type = SCM_RIGHTS;
126 cmsg.fd = fd;
127 msghdr.msg_control = &cmsg;
128 msghdr.msg_controllen = sizeof(cmsg);
129 msghdr.msg_flags = 0;
130 #endif /* HAVE_MSGHDR_ACCRIGHTS */
132 if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
133 if (ret == -1)
135 if (errno == EPIPE) CLIENT_Die();
136 server_perror( "sendmsg" );
138 server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
141 /***********************************************************************
142 * wait_reply
144 * Wait for a reply from the server.
146 static unsigned int wait_reply(void)
148 int ret;
149 unsigned int res;
151 for (;;)
153 if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
154 return res;
155 if (ret == -1)
157 if (errno == EINTR) continue;
158 if (errno == EPIPE) CLIENT_Die();
159 server_perror("read");
161 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
162 server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
167 /***********************************************************************
168 * wait_reply_fd
170 * Wait for a reply from the server, when a file descriptor is passed.
172 static unsigned int wait_reply_fd( int *fd )
174 struct iovec vec;
175 int ret;
176 unsigned int res;
178 #ifdef HAVE_MSGHDR_ACCRIGHTS
179 struct msghdr msghdr;
181 *fd = -1;
182 msghdr.msg_accrights = (void *)fd;
183 msghdr.msg_accrightslen = sizeof(*fd);
184 #else /* HAVE_MSGHDR_ACCRIGHTS */
185 struct msghdr msghdr;
186 struct cmsg_fd cmsg;
188 cmsg.len = sizeof(cmsg);
189 cmsg.level = SOL_SOCKET;
190 cmsg.type = SCM_RIGHTS;
191 cmsg.fd = -1;
192 msghdr.msg_control = &cmsg;
193 msghdr.msg_controllen = sizeof(cmsg);
194 msghdr.msg_flags = 0;
195 #endif /* HAVE_MSGHDR_ACCRIGHTS */
197 msghdr.msg_name = NULL;
198 msghdr.msg_namelen = 0;
199 msghdr.msg_iov = &vec;
200 msghdr.msg_iovlen = 1;
201 vec.iov_base = (void *)&res;
202 vec.iov_len = sizeof(res);
204 for (;;)
206 if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
208 #ifndef HAVE_MSGHDR_ACCRIGHTS
209 *fd = cmsg.fd;
210 #endif
211 return res;
213 if (ret == -1)
215 if (errno == EINTR) continue;
216 if (errno == EPIPE) CLIENT_Die();
217 server_perror("recvmsg");
219 if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
220 server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
225 /***********************************************************************
226 * server_call
228 * Perform a server call.
230 unsigned int server_call( enum request req )
232 unsigned int res;
234 send_request( req );
235 res = wait_reply();
236 if (res) SetLastError( res );
237 return res; /* error code */
241 /***********************************************************************
242 * server_call_fd
244 * Perform a server call, passing a file descriptor.
245 * If *fd is != -1, it will be passed to the server.
246 * If the server passes an fd, it will be stored into *fd.
248 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
250 unsigned int res;
252 if (fd_out == -1) send_request( req );
253 else send_request_fd( req, fd_out );
255 if (fd_in) res = wait_reply_fd( fd_in );
256 else res = wait_reply();
257 if (res) SetLastError( res );
258 return res; /* error code */
262 /***********************************************************************
263 * CLIENT_InitServer
265 * Start the server and create the initial socket pair.
267 int CLIENT_InitServer(void)
269 int fd[2];
270 char buffer[16];
271 extern void create_initial_thread( int fd );
273 if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
275 perror("socketpair");
276 exit(1);
278 switch(fork())
280 case -1: /* error */
281 perror("fork");
282 exit(1);
283 case 0: /* child */
284 close( fd[1] );
285 break;
286 default: /* parent */
287 close( fd[0] );
288 sprintf( buffer, "%d", fd[1] );
289 /*#define EXEC_SERVER*/
290 #ifdef EXEC_SERVER
291 execlp( "wineserver", "wineserver", buffer, NULL );
292 execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
293 execl( "./server/wineserver", "wineserver", buffer, NULL );
294 #endif
295 create_initial_thread( fd[1] );
296 exit(0);
298 return fd[0];
302 /***********************************************************************
303 * CLIENT_InitThread
305 * Send an init thread request. Return 0 if OK.
307 int CLIENT_InitThread(void)
309 struct init_thread_request *req;
310 TEB *teb = NtCurrentTeb();
311 int fd;
313 if (wait_reply_fd( &fd ) || (fd == -1))
314 server_protocol_error( "no fd passed on first request\n" );
315 if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
316 teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
317 close( fd );
318 if (teb->buffer == (void*)-1) server_perror( "mmap" );
320 req = get_req_buffer();
321 req->unix_pid = getpid();
322 req->teb = teb;
323 if (server_call( REQ_INIT_THREAD )) return -1;
324 teb->process->server_pid = req->pid;
325 teb->tid = req->tid;
326 return 0;
330 /***********************************************************************
331 * CLIENT_SetDebug
333 * Send a set debug level request. Return 0 if OK.
335 int CLIENT_SetDebug( int level )
337 struct set_debug_request *req = get_req_buffer();
338 req->level = level;
339 return server_call( REQ_SET_DEBUG );
342 /***********************************************************************
343 * CLIENT_DebuggerRequest
345 * Send a debugger support request. Return 0 if OK.
347 int CLIENT_DebuggerRequest( int op )
349 struct debugger_request *req = get_req_buffer();
350 req->op = op;
351 return server_call( REQ_DEBUGGER );