2 * daemon-messages.c: Communications to and from the handle daemon
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 /* Freebsd needs this included explicitly, but it doesn't hurt on Linux */
20 #ifndef HAVE_MSG_NOSIGNAL
24 #include <mono/io-layer/wapi.h>
25 #include <mono/io-layer/daemon-messages.h>
27 /* Solaris doesn't define these */
29 #define CMSG_LEN(size) (sizeof (struct cmsghdr) + (size))
32 #define CMSG_SPACE(size) (sizeof (struct cmsghdr) + (size))
35 /* Send request on fd, wait for response (called by applications, not
36 * the daemon, indirectly through _wapi_daemon_request_response and
37 * _wapi_daemon_request_response_with_fds)
39 static void _wapi_daemon_request_response_internal (int fd,
41 WapiHandleResponse *resp)
43 static pthread_mutex_t req_mutex=PTHREAD_MUTEX_INITIALIZER;
45 #ifndef HAVE_MSG_NOSIGNAL
46 void (*old_sigpipe)(int);
49 /* Serialise requests to the daemon from the same process. We
50 * rely on request turnaround time being minimal anyway, so
51 * performance shouldnt suffer from the mutex.
53 pthread_mutex_lock (&req_mutex);
55 #ifdef HAVE_MSG_NOSIGNAL
56 ret=sendmsg (fd, msg, MSG_NOSIGNAL);
58 old_sigpipe = signal (SIGPIPE, SIG_IGN);
59 ret=sendmsg (fd, msg, 0);
61 if(ret!=sizeof(WapiHandleRequest)) {
63 g_critical (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
66 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
68 g_assert_not_reached ();
72 #ifdef HAVE_MSG_NOSIGNAL
73 ret=recv (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL);
75 ret=recv (fd, resp, sizeof(WapiHandleResponse), 0);
76 signal (SIGPIPE, old_sigpipe);
80 g_critical (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
83 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
85 g_assert_not_reached ();
89 pthread_mutex_unlock (&req_mutex);
92 /* Send request on fd with filedescriptors, wait for response (called
93 * by applications, not the daemon)
95 void _wapi_daemon_request_response_with_fds (int fd, WapiHandleRequest *req,
96 WapiHandleResponse *resp,
97 int in_fd, int out_fd, int err_fd)
99 struct msghdr msg={0};
100 struct cmsghdr *cmsg;
102 char cmsgdata[CMSG_SPACE (sizeof(int)*3)];
109 msg.msg_control=cmsgdata;
110 msg.msg_controllen=sizeof(cmsgdata);
114 iov.iov_len=sizeof(WapiHandleRequest);
116 cmsg=CMSG_FIRSTHDR (&msg);
117 cmsg->cmsg_len=CMSG_LEN (sizeof(int)*3);
118 cmsg->cmsg_level=SOL_SOCKET;
119 cmsg->cmsg_type=SCM_RIGHTS;
120 fdptr=(int *)CMSG_DATA (cmsg);
125 msg.msg_controllen=CMSG_SPACE (sizeof(int)*3);
127 _wapi_daemon_request_response_internal (fd, &msg, resp);
130 /* Send request on fd, wait for response (called by applications, not
133 void _wapi_daemon_request_response (int fd, WapiHandleRequest *req,
134 WapiHandleResponse *resp)
136 struct msghdr msg={0};
143 msg.msg_control=NULL;
144 msg.msg_controllen=0;
148 iov.iov_len=sizeof(WapiHandleRequest);
150 _wapi_daemon_request_response_internal (fd, &msg, resp);
153 /* Read request on fd (called by the daemon) */
154 int _wapi_daemon_request (int fd, WapiHandleRequest *req, int *fds,
160 struct cmsghdr *cmsg;
161 guchar cmsgdata[CMSG_SPACE (sizeof(int)*3)];
167 msg.msg_control=cmsgdata;
168 msg.msg_controllen=sizeof(cmsgdata);
171 iov.iov_len=sizeof(WapiHandleRequest);
173 #ifdef HAVE_MSG_NOSIGNAL
174 ret=recvmsg (fd, &msg, MSG_NOSIGNAL);
176 ret=recvmsg (fd, &msg, 0);
178 if(ret==-1 || ret!= sizeof(WapiHandleRequest)) {
179 /* Make sure we dont do anything with this response */
180 req->type=WapiHandleRequestType_Error;
183 g_warning (G_GNUC_PRETTY_FUNCTION ": Recv error: %s",
186 /* The next loop around poll() should tidy up */
190 if(msg.msg_flags & MSG_OOB) {
191 g_message (G_GNUC_PRETTY_FUNCTION ": OOB data received");
193 if(msg.msg_flags & MSG_CTRUNC) {
194 g_message (G_GNUC_PRETTY_FUNCTION ": ancillary data was truncated");
196 g_message (G_GNUC_PRETTY_FUNCTION ": msg.msg_controllen=%d",
200 cmsg=CMSG_FIRSTHDR (&msg);
201 if(cmsg!=NULL && cmsg->cmsg_level==SOL_SOCKET &&
202 cmsg->cmsg_type==SCM_RIGHTS) {
204 g_message (G_GNUC_PRETTY_FUNCTION ": cmsg->cmsg_len=%d",
206 g_message (G_GNUC_PRETTY_FUNCTION
207 ": cmsg->level=%d cmsg->type=%d", cmsg->cmsg_level,
211 memcpy (fds, (int *)CMSG_DATA (cmsg), sizeof(int)*3);
215 g_message (G_GNUC_PRETTY_FUNCTION
216 ": fd[0]=%d, fd[1]=%d, fd[2]=%d", fds[0], fds[1],
221 g_message (G_GNUC_PRETTY_FUNCTION ": no ancillary data");
229 /* Send response on fd (called by the daemon) */
230 int _wapi_daemon_response (int fd, WapiHandleResponse *resp)
234 #ifdef HAVE_MSG_NOSIGNAL
235 ret=send (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL);
237 ret=send (fd, resp, sizeof(WapiHandleResponse), 0);
240 if(ret==-1 || ret != sizeof(WapiHandleResponse)) {
241 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
243 /* The next loop around poll() should tidy up */