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 (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
100 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
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 (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
124 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
126 g_assert_not_reached ();
130 ret = mono_mutex_unlock (&req_mutex);
133 pthread_cleanup_pop (0);
136 /* Send request on fd with filedescriptors, wait for response (called
137 * by applications, not the daemon)
139 void _wapi_daemon_request_response_with_fds (int fd, WapiHandleRequest *req,
140 WapiHandleResponse *resp,
141 int in_fd, int out_fd, int err_fd)
143 struct msghdr msg={0};
144 struct cmsghdr *cmsg;
146 char cmsgdata[CMSG_SPACE (sizeof(int)*3)];
153 msg.msg_control=cmsgdata;
154 msg.msg_controllen=sizeof(cmsgdata);
158 iov.iov_len=sizeof(WapiHandleRequest);
160 cmsg=CMSG_FIRSTHDR (&msg);
161 cmsg->cmsg_len=CMSG_LEN (sizeof(int)*3);
162 cmsg->cmsg_level=SOL_SOCKET;
163 cmsg->cmsg_type=SCM_RIGHTS;
164 fdptr=(int *)CMSG_DATA (cmsg);
169 msg.msg_controllen=CMSG_SPACE (sizeof(int)*3);
171 _wapi_daemon_request_response_internal (fd, &msg, resp);
174 /* Send request on fd, wait for response (called by applications, not
177 void _wapi_daemon_request_response (int fd, WapiHandleRequest *req,
178 WapiHandleResponse *resp)
180 struct msghdr msg={0};
187 msg.msg_control=NULL;
188 msg.msg_controllen=0;
192 iov.iov_len=sizeof(WapiHandleRequest);
194 _wapi_daemon_request_response_internal (fd, &msg, resp);
197 /* Read request on fd (called by the daemon) */
198 int _wapi_daemon_request (int fd, WapiHandleRequest *req, int *fds,
204 struct cmsghdr *cmsg;
205 guchar cmsgdata[CMSG_SPACE (sizeof(int)*3)];
211 msg.msg_control=cmsgdata;
212 msg.msg_controllen=sizeof(cmsgdata);
215 iov.iov_len=sizeof(WapiHandleRequest);
218 #ifdef HAVE_MSG_NOSIGNAL
219 ret=recvmsg (fd, &msg, MSG_NOSIGNAL);
221 ret=recvmsg (fd, &msg, 0);
224 while (ret==-1 && errno==EINTR);
226 if(ret==-1 || ret!= sizeof(WapiHandleRequest)) {
227 /* Make sure we dont do anything with this response */
228 req->type=WapiHandleRequestType_Error;
230 g_warning (G_GNUC_PRETTY_FUNCTION ": Recv error: %s",
232 /* The next loop around poll() should tidy up */
236 if(msg.msg_flags & MSG_OOB) {
237 g_message (G_GNUC_PRETTY_FUNCTION ": OOB data received");
239 if(msg.msg_flags & MSG_CTRUNC) {
240 g_message (G_GNUC_PRETTY_FUNCTION ": ancillary data was truncated");
242 g_message (G_GNUC_PRETTY_FUNCTION ": msg.msg_controllen=%d",
246 cmsg=CMSG_FIRSTHDR (&msg);
247 if(cmsg!=NULL && cmsg->cmsg_level==SOL_SOCKET &&
248 cmsg->cmsg_type==SCM_RIGHTS) {
249 LOGDEBUG (G_GNUC_PRETTY_FUNCTION ": cmsg->cmsg_len=%d", cmsg->cmsg_len);
250 LOGDEBUG (G_GNUC_PRETTY_FUNCTION ": cmsg->level=%d cmsg->type=%d", cmsg->cmsg_level, cmsg->cmsg_type);
252 memcpy (fds, (int *)CMSG_DATA (cmsg), sizeof(int)*3);
255 LOGDEBUG (G_GNUC_PRETTY_FUNCTION ": fd[0]=%d, fd[1]=%d, fd[2]=%d", fds[0], fds[1], fds[2]);
257 LOGDEBUG (G_GNUC_PRETTY_FUNCTION ": no ancillary data");
264 /* Send response on fd (called by the daemon) */
265 int _wapi_daemon_response (int fd, WapiHandleResponse *resp)
270 #ifdef HAVE_MSG_NOSIGNAL
271 ret=send (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL);
273 ret=send (fd, resp, sizeof(WapiHandleResponse), 0);
276 while (ret==-1 && errno==EINTR);
279 if(ret==-1 || ret != sizeof(WapiHandleResponse)) {
280 g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
282 /* The next loop around poll() should tidy up */