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 */
22 #ifndef HAVE_MSG_NOSIGNAL
26 #include <mono/io-layer/wapi.h>
27 #include <mono/io-layer/daemon-messages.h>
29 /* Solaris doesn't define these */
31 #define CMSG_LEN(size) (sizeof (struct cmsghdr) + (size))
34 #define CMSG_SPACE(size) (sizeof (struct cmsghdr) + (size))
38 // #define LOGDEBUG(...) g_message(__VA_ARGS__)
40 static mono_mutex_t req_mutex
;
41 static mono_once_t attr_key_once
= MONO_ONCE_INIT
;
42 static mono_mutexattr_t attr
;
44 static void attr_init (void)
48 ret
= mono_mutexattr_init (&attr
);
51 ret
= mono_mutexattr_settype (&attr
, MONO_MUTEX_RECURSIVE
);
54 ret
= mono_mutex_init (&req_mutex
, &attr
);
58 /* Send request on fd, wait for response (called by applications, not
59 * the daemon, indirectly through _wapi_daemon_request_response and
60 * _wapi_daemon_request_response_with_fds)
62 static void _wapi_daemon_request_response_internal (int fd
,
64 WapiHandleResponse
*resp
)
67 #ifndef HAVE_MSG_NOSIGNAL
68 void (*old_sigpipe
)(int);
71 mono_once (&attr_key_once
, attr_init
);
73 /* Serialise requests to the daemon from the same process. We
74 * rely on request turnaround time being minimal anyway, so
75 * performance shouldnt suffer from the mutex.
77 pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup
,
79 ret
= mono_mutex_lock (&req_mutex
);
82 #ifdef HAVE_MSG_NOSIGNAL
84 ret
=sendmsg (fd
, msg
, MSG_NOSIGNAL
);
86 while (ret
==-1 && errno
==EINTR
);
88 old_sigpipe
= signal (SIGPIPE
, SIG_IGN
);
90 ret
=sendmsg (fd
, msg
, 0);
92 while (ret
==-1 && errno
==EINTR
);
95 if(ret
!=sizeof(WapiHandleRequest
)) {
97 g_critical ("%s: The handle daemon vanished!", __func__
);
100 g_warning ("%s: Send error: %s", __func__
,
102 g_assert_not_reached ();
106 #ifdef HAVE_MSG_NOSIGNAL
108 ret
=recv (fd
, resp
, sizeof(WapiHandleResponse
), MSG_NOSIGNAL
);
110 while (ret
==-1 && errno
==EINTR
);
113 ret
=recv (fd
, resp
, sizeof(WapiHandleResponse
), 0);
115 while (ret
==-1 && errno
==EINTR
);
116 signal (SIGPIPE
, old_sigpipe
);
121 g_critical ("%s: The handle daemon vanished!", __func__
);
124 g_warning ("%s: Send error: %s", __func__
, strerror (errno
));
125 g_assert_not_reached ();
129 ret
= mono_mutex_unlock (&req_mutex
);
132 pthread_cleanup_pop (0);
135 /* Send request on fd with filedescriptors, wait for response (called
136 * by applications, not the daemon)
138 void _wapi_daemon_request_response_with_fds (int fd
, WapiHandleRequest
*req
,
139 WapiHandleResponse
*resp
,
140 int in_fd
, int out_fd
, int err_fd
)
142 struct msghdr msg
={0};
143 struct cmsghdr
*cmsg
;
145 char cmsgdata
[CMSG_SPACE (sizeof(int)*3)];
152 msg
.msg_control
=cmsgdata
;
153 msg
.msg_controllen
=sizeof(cmsgdata
);
157 iov
.iov_len
=sizeof(WapiHandleRequest
);
159 cmsg
=CMSG_FIRSTHDR (&msg
);
160 cmsg
->cmsg_len
=CMSG_LEN (sizeof(int)*3);
161 cmsg
->cmsg_level
=SOL_SOCKET
;
162 cmsg
->cmsg_type
=SCM_RIGHTS
;
163 fdptr
=(int *)CMSG_DATA (cmsg
);
168 msg
.msg_controllen
=CMSG_SPACE (sizeof(int)*3);
170 _wapi_daemon_request_response_internal (fd
, &msg
, resp
);
173 /* Send request on fd, wait for response (called by applications, not
176 void _wapi_daemon_request_response (int fd
, WapiHandleRequest
*req
,
177 WapiHandleResponse
*resp
)
179 struct msghdr msg
={0};
186 msg
.msg_control
=NULL
;
187 msg
.msg_controllen
=0;
191 iov
.iov_len
=sizeof(WapiHandleRequest
);
193 _wapi_daemon_request_response_internal (fd
, &msg
, resp
);
196 /* Read request on fd (called by the daemon) */
197 int _wapi_daemon_request (int fd
, WapiHandleRequest
*req
, int *fds
,
203 struct cmsghdr
*cmsg
;
204 guchar cmsgdata
[CMSG_SPACE (sizeof(int)*3)];
210 msg
.msg_control
=cmsgdata
;
211 msg
.msg_controllen
=sizeof(cmsgdata
);
214 iov
.iov_len
=sizeof(WapiHandleRequest
);
217 #ifdef HAVE_MSG_NOSIGNAL
218 ret
=recvmsg (fd
, &msg
, MSG_NOSIGNAL
);
220 ret
=recvmsg (fd
, &msg
, 0);
223 while (ret
==-1 && errno
==EINTR
);
225 if(ret
==-1 || ret
!= sizeof(WapiHandleRequest
)) {
226 /* Make sure we dont do anything with this response */
227 req
->type
=WapiHandleRequestType_Error
;
229 g_warning ("%s: Recv error: %s", __func__
, strerror (errno
));
230 /* The next loop around poll() should tidy up */
234 if(msg
.msg_flags
& MSG_OOB
) {
235 g_message ("%s: OOB data received", __func__
);
237 if(msg
.msg_flags
& MSG_CTRUNC
) {
238 g_message ("%s: ancillary data was truncated", __func__
);
240 g_message ("%s: msg.msg_controllen=%d", __func__
, msg
.msg_controllen
);
243 cmsg
=CMSG_FIRSTHDR (&msg
);
244 if(cmsg
!=NULL
&& cmsg
->cmsg_level
==SOL_SOCKET
&&
245 cmsg
->cmsg_type
==SCM_RIGHTS
) {
246 LOGDEBUG ("%s: cmsg->cmsg_len=%d", __func__
, cmsg
->cmsg_len
);
247 LOGDEBUG ("%s: cmsg->level=%d cmsg->type=%d", __func__
, cmsg
->cmsg_level
, cmsg
->cmsg_type
);
249 memcpy (fds
, (int *)CMSG_DATA (cmsg
), sizeof(int)*3);
252 LOGDEBUG ("%s: fd[0]=%d, fd[1]=%d, fd[2]=%d", __func__
, fds
[0], fds
[1], fds
[2]);
254 LOGDEBUG ("%s: no ancillary data", __func__
);
261 /* Send response on fd (called by the daemon) */
262 int _wapi_daemon_response (int fd
, WapiHandleResponse
*resp
)
267 #ifdef HAVE_MSG_NOSIGNAL
268 ret
=send (fd
, resp
, sizeof(WapiHandleResponse
), MSG_NOSIGNAL
);
270 ret
=send (fd
, resp
, sizeof(WapiHandleResponse
), 0);
273 while (ret
==-1 && errno
==EINTR
);
276 if(ret
==-1 || ret
!= sizeof(WapiHandleResponse
)) {
277 g_warning ("%s: Send error: %s", __func__
, strerror (errno
));
278 /* The next loop around poll() should tidy up */