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 static mono_mutex_t req_mutex
;
36 static mono_once_t attr_key_once
= MONO_ONCE_INIT
;
37 static mono_mutexattr_t attr
;
39 static void attr_init (void)
43 ret
= mono_mutexattr_init (&attr
);
46 ret
= mono_mutexattr_settype (&attr
, MONO_MUTEX_RECURSIVE
);
49 ret
= mono_mutex_init (&req_mutex
, &attr
);
53 /* Send request on fd, wait for response (called by applications, not
54 * the daemon, indirectly through _wapi_daemon_request_response and
55 * _wapi_daemon_request_response_with_fds)
57 static void _wapi_daemon_request_response_internal (int fd
,
59 WapiHandleResponse
*resp
)
62 #ifndef HAVE_MSG_NOSIGNAL
63 void (*old_sigpipe
)(int);
66 mono_once (&attr_key_once
, attr_init
);
68 /* Serialise requests to the daemon from the same process. We
69 * rely on request turnaround time being minimal anyway, so
70 * performance shouldnt suffer from the mutex.
72 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup
,
74 ret
= mono_mutex_lock (&req_mutex
);
77 #ifdef HAVE_MSG_NOSIGNAL
79 ret
=sendmsg (fd
, msg
, MSG_NOSIGNAL
);
81 while (ret
==-1 && errno
==EINTR
);
83 old_sigpipe
= signal (SIGPIPE
, SIG_IGN
);
85 ret
=sendmsg (fd
, msg
, 0);
87 while (ret
==-1 && errno
==EINTR
);
90 if(ret
!=sizeof(WapiHandleRequest
)) {
92 g_critical (G_GNUC_PRETTY_FUNCTION
": The handle daemon vanished!");
95 g_warning (G_GNUC_PRETTY_FUNCTION
": Send error: %s",
97 g_assert_not_reached ();
101 #ifdef HAVE_MSG_NOSIGNAL
103 ret
=recv (fd
, resp
, sizeof(WapiHandleResponse
), MSG_NOSIGNAL
);
105 while (ret
==-1 && errno
==EINTR
);
108 ret
=recv (fd
, resp
, sizeof(WapiHandleResponse
), 0);
110 while (ret
==-1 && errno
==EINTR
);
111 signal (SIGPIPE
, old_sigpipe
);
116 g_critical (G_GNUC_PRETTY_FUNCTION
": The handle daemon vanished!");
119 g_warning (G_GNUC_PRETTY_FUNCTION
": Send error: %s",
121 g_assert_not_reached ();
125 ret
= mono_mutex_unlock (&req_mutex
);
128 pthread_cleanup_pop (0);
131 /* Send request on fd with filedescriptors, wait for response (called
132 * by applications, not the daemon)
134 void _wapi_daemon_request_response_with_fds (int fd
, WapiHandleRequest
*req
,
135 WapiHandleResponse
*resp
,
136 int in_fd
, int out_fd
, int err_fd
)
138 struct msghdr msg
={0};
139 struct cmsghdr
*cmsg
;
141 char cmsgdata
[CMSG_SPACE (sizeof(int)*3)];
148 msg
.msg_control
=cmsgdata
;
149 msg
.msg_controllen
=sizeof(cmsgdata
);
153 iov
.iov_len
=sizeof(WapiHandleRequest
);
155 cmsg
=CMSG_FIRSTHDR (&msg
);
156 cmsg
->cmsg_len
=CMSG_LEN (sizeof(int)*3);
157 cmsg
->cmsg_level
=SOL_SOCKET
;
158 cmsg
->cmsg_type
=SCM_RIGHTS
;
159 fdptr
=(int *)CMSG_DATA (cmsg
);
164 msg
.msg_controllen
=CMSG_SPACE (sizeof(int)*3);
166 _wapi_daemon_request_response_internal (fd
, &msg
, resp
);
169 /* Send request on fd, wait for response (called by applications, not
172 void _wapi_daemon_request_response (int fd
, WapiHandleRequest
*req
,
173 WapiHandleResponse
*resp
)
175 struct msghdr msg
={0};
182 msg
.msg_control
=NULL
;
183 msg
.msg_controllen
=0;
187 iov
.iov_len
=sizeof(WapiHandleRequest
);
189 _wapi_daemon_request_response_internal (fd
, &msg
, resp
);
192 /* Read request on fd (called by the daemon) */
193 int _wapi_daemon_request (int fd
, WapiHandleRequest
*req
, int *fds
,
199 struct cmsghdr
*cmsg
;
200 guchar cmsgdata
[CMSG_SPACE (sizeof(int)*3)];
206 msg
.msg_control
=cmsgdata
;
207 msg
.msg_controllen
=sizeof(cmsgdata
);
210 iov
.iov_len
=sizeof(WapiHandleRequest
);
213 #ifdef HAVE_MSG_NOSIGNAL
214 ret
=recvmsg (fd
, &msg
, MSG_NOSIGNAL
);
216 ret
=recvmsg (fd
, &msg
, 0);
219 while (ret
==-1 && errno
==EINTR
);
221 if(ret
==-1 || ret
!= sizeof(WapiHandleRequest
)) {
222 /* Make sure we dont do anything with this response */
223 req
->type
=WapiHandleRequestType_Error
;
226 g_warning (G_GNUC_PRETTY_FUNCTION
": Recv error: %s",
229 /* The next loop around poll() should tidy up */
233 if(msg
.msg_flags
& MSG_OOB
) {
234 g_message (G_GNUC_PRETTY_FUNCTION
": OOB data received");
236 if(msg
.msg_flags
& MSG_CTRUNC
) {
237 g_message (G_GNUC_PRETTY_FUNCTION
": ancillary data was truncated");
239 g_message (G_GNUC_PRETTY_FUNCTION
": msg.msg_controllen=%d",
243 cmsg
=CMSG_FIRSTHDR (&msg
);
244 if(cmsg
!=NULL
&& cmsg
->cmsg_level
==SOL_SOCKET
&&
245 cmsg
->cmsg_type
==SCM_RIGHTS
) {
247 g_message (G_GNUC_PRETTY_FUNCTION
": cmsg->cmsg_len=%d",
249 g_message (G_GNUC_PRETTY_FUNCTION
250 ": cmsg->level=%d cmsg->type=%d", cmsg
->cmsg_level
,
254 memcpy (fds
, (int *)CMSG_DATA (cmsg
), sizeof(int)*3);
258 g_message (G_GNUC_PRETTY_FUNCTION
259 ": fd[0]=%d, fd[1]=%d, fd[2]=%d", fds
[0], fds
[1],
264 g_message (G_GNUC_PRETTY_FUNCTION
": no ancillary data");
272 /* Send response on fd (called by the daemon) */
273 int _wapi_daemon_response (int fd
, WapiHandleResponse
*resp
)
278 #ifdef HAVE_MSG_NOSIGNAL
279 ret
=send (fd
, resp
, sizeof(WapiHandleResponse
), MSG_NOSIGNAL
);
281 ret
=send (fd
, resp
, sizeof(WapiHandleResponse
), 0);
284 while (ret
==-1 && errno
==EINTR
);
288 if(ret
==-1 || ret
!= sizeof(WapiHandleResponse
)) {
289 g_warning (G_GNUC_PRETTY_FUNCTION
": Send error: %s",
291 /* The next loop around poll() should tidy up */