2 * daemon.c: The handle daemon
5 * Dick Porter (dick@ximian.com)
7 * (C) 2002 Ximian, Inc.
14 #include <sys/types.h>
15 #include <sys/socket.h>
24 #include <mono/io-layer/io-layer.h>
25 #include <mono/io-layer/handles-private.h>
26 #include <mono/io-layer/wapi-private.h>
27 #include <mono/io-layer/daemon-messages.h>
28 #include <mono/io-layer/timefuncs-private.h>
29 #include <mono/io-layer/daemon-private.h>
33 /* Array to hold the file descriptor we are currently polling */
34 static struct pollfd *pollfds=NULL;
35 /* Keep track of the size and usage of pollfds */
36 static int nfds=0, maxfds=0;
37 /* Array to keep track of arrays of handles that belong to a given
38 * client. handle_refs[0] is used by the daemon itself
40 static guint32 **handle_refs=NULL;
41 /* The socket which we listen to new connections on */
44 /* Set to TRUE by the SIGCHLD signal handler */
45 static volatile gboolean check_processes=FALSE;
47 /* Deletes the shared memory segment. If we're exiting on error,
48 * clients will get EPIPEs.
50 static void cleanup (void)
55 /* If there is only one socket, and no child processes, we can exit.
56 * We test for child processes by counting handle references held by
59 static void maybe_exit (void)
61 guint32 *open_handles=handle_refs[0], i;
64 g_message (G_GNUC_PRETTY_FUNCTION ": Seeing if we should exit");
69 g_message (G_GNUC_PRETTY_FUNCTION ": Still got clients");
74 for(i=0; i<_WAPI_MAX_HANDLES; i++) {
75 if(open_handles[i]>0) {
77 g_message (G_GNUC_PRETTY_FUNCTION
78 ": Still got handle references");
85 g_message (G_GNUC_PRETTY_FUNCTION ": Byebye");
96 * Called if daemon receives a SIGTERM or SIGINT
98 static void signal_handler (int unused)
108 * Called if daemon receives a SIGCHLD, and notes that a process needs
109 * to be wait()ed for.
111 static void sigchld_handler (int unused)
113 /* Notice that a child process died */
114 check_processes=TRUE;
120 * Bind signals and attach to shared memory
122 static void startup (void)
128 sa.sa_handler=signal_handler;
129 sigemptyset (&sa.sa_mask);
131 sigaction (SIGINT, &sa, NULL);
132 sigaction (SIGTERM, &sa, NULL);
134 #ifndef HAVE_MSG_NOSIGNAL
135 sa.sa_handler=SIG_IGN;
136 sigaction (SIGPIPE, &sa, NULL);
139 sa.sa_handler=sigchld_handler;
140 sa.sa_flags=SA_NOCLDSTOP;
141 sigaction (SIGCHLD, &sa, NULL);
143 _wapi_shared_data=_wapi_shm_attach (TRUE, &success, &shm_id);
145 g_error ("Failed to attach shared memory! (tried shared memory ID 0x%x)", shm_id);
149 /* Leave the first byte NULL so we create the socket in the
150 * abstrace namespace, not on the filesystem. (Lets see how
151 * portable _that_ is :)
153 * The name is intended to be unique, not cryptographically
156 snprintf (_wapi_shared_data->daemon+1, 106,
157 "mono-handle-daemon-%d-%d-%ld", getuid (), getpid (),
164 * @idx: idx into pollfds
165 * @handle: handle to inc refcnt
167 * Increase ref count of handle for idx's filedescr. and the
168 * shm. Handle 0 is ignored.
170 static void ref_handle (guint32 idx, guint32 handle)
172 guint32 *open_handles=handle_refs[idx];
178 _wapi_shared_data->handles[handle].ref++;
179 open_handles[handle]++;
182 g_message (G_GNUC_PRETTY_FUNCTION
183 ": handle 0x%x ref now %d (%d this process)", handle,
184 _wapi_shared_data->handles[handle].ref,
185 open_handles[handle]);
191 * @idx: idx into pollfds
192 * @handle: handle to inc refcnt
194 * Decrease ref count of handle for idx's filedescr. and the shm. If
195 * global ref count reaches 0 it is free'ed. Return TRUE if the local
196 * ref count is 0. Handle 0 is ignored.
198 static gboolean unref_handle (guint32 idx, guint32 handle)
200 guint32 *open_handles=handle_refs[idx];
201 gboolean destroy=FALSE;
207 if (open_handles[handle] == 0) {
208 g_warning(G_GNUC_PRETTY_FUNCTION
209 ": unref on %d called when ref was already 0",
214 _wapi_shared_data->handles[handle].ref--;
215 open_handles[handle]--;
218 g_message (G_GNUC_PRETTY_FUNCTION
219 ": handle 0x%x ref now %d (%d this process)", handle,
220 _wapi_shared_data->handles[handle].ref,
221 open_handles[handle]);
224 if(open_handles[handle]==0) {
225 /* This client has released the handle */
229 if(_wapi_shared_data->handles[handle].ref==0) {
230 if (open_handles[handle]!=0) {
231 g_warning (G_GNUC_PRETTY_FUNCTION ": per-process open_handles mismatch, set to %d, should be 0", open_handles[handle]);
235 g_message (G_GNUC_PRETTY_FUNCTION ": Destroying handle 0x%x",
239 _wapi_handle_ops_close_shared (GUINT_TO_POINTER (handle));
241 _wapi_shared_data->handles[handle].type=WAPI_HANDLE_UNUSED;
242 mono_mutex_destroy (&_wapi_shared_data->handles[handle].signal_mutex);
243 pthread_cond_destroy (&_wapi_shared_data->handles[handle].signal_cond);
244 memset (&_wapi_shared_data->handles[handle].u, '\0', sizeof(_wapi_shared_data->handles[handle].u));
248 /* The daemon released a reference, so see if it's
259 * @fd: Filehandle to add
261 * Add filedescriptor to the pollfds array, expand if necessary
263 static void add_fd(int fd)
266 /* extend the array */
268 /* no need to memset the extra memory, we init it
269 * before use anyway */
270 pollfds=g_renew (struct pollfd, pollfds, maxfds);
271 handle_refs=g_renew (guint32*, handle_refs, maxfds);
275 pollfds[nfds].events=POLLIN;
276 pollfds[nfds].revents=0;
278 handle_refs[nfds]=g_new0 (guint32, _WAPI_MAX_HANDLES);
285 * @idx: idx into pollfds to remove
287 * Close filedescriptor and remove it from the pollfds array. Closes
288 * all handles that it may have open. If only main_sock is open, the
289 * daemon is shut down.
291 static void rem_fd(int idx)
293 guint32 *open_handles=handle_refs[idx], handle_count;
297 /* We shouldn't be deleting the daemon's fd */
298 g_warning (G_GNUC_PRETTY_FUNCTION ": Deleting daemon fd!");
304 g_message (G_GNUC_PRETTY_FUNCTION ": Removing client at %d", idx);
307 close(pollfds[idx].fd);
309 for(i=0; i<_WAPI_MAX_HANDLES; i++) {
310 handle_count=open_handles[i];
312 for(j=0; j<handle_count; j++) {
314 g_message (G_GNUC_PRETTY_FUNCTION ": closing handle 0x%x for client at index %d", i, idx);
316 /* Ignore the hint to the client to destroy
317 * the handle private data
319 unref_handle (idx, i);
325 /* Just the master socket left, so see if we can
331 memset(&pollfds[idx], '\0', sizeof(struct pollfd));
332 g_free (handle_refs[idx]);
335 memmove(&pollfds[idx], &pollfds[idx+1],
336 sizeof(struct pollfd) * (nfds-idx));
337 memmove (&handle_refs[idx], &handle_refs[idx+1],
338 sizeof(guint32) * (nfds-idx));
342 static gboolean process_compare (gpointer handle, gpointer user_data)
344 struct _WapiHandle_process *process_handle;
348 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
349 (gpointer *)&process_handle, NULL);
351 g_warning (G_GNUC_PRETTY_FUNCTION
352 ": error looking up process handle %p", handle);
356 pid=GPOINTER_TO_UINT (user_data);
357 if(process_handle->id==pid) {
364 static gboolean process_thread_compare (gpointer handle, gpointer user_data)
366 struct _WapiHandle_thread *thread_handle;
369 ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
370 (gpointer *)&thread_handle, NULL);
372 g_warning (G_GNUC_PRETTY_FUNCTION
373 ": error looking up thread handle %p", handle);
377 if(thread_handle->process_handle==user_data) {
378 /* Signal the handle. Don't use
379 * _wapi_handle_set_signal_state() unless we have
380 * process-shared pthread support.
383 g_message (G_GNUC_PRETTY_FUNCTION ": Set thread handle %p signalled, because its process died", handle);
386 thread_handle->exitstatus=0;
388 #ifdef _POSIX_THREAD_PROCESS_SHARED
389 _wapi_handle_lock_handle (handle);
390 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
391 _wapi_handle_unlock_handle (handle);
393 /* Just tweak the signal state directly. This is not
394 * recommended behaviour, but it works for threads
395 * because they can never become unsignalled. There
396 * are some nasty kludges in the handle waiting code
397 * to cope with missing condition signals for when
398 * process-shared pthread support is missing.
400 _wapi_shared_data->handles[GPOINTER_TO_UINT (handle)].signalled=TRUE;
401 #endif /* _POSIX_THREAD_PROCESS_SHARED */
404 /* Return false to keep searching */
408 /* Find the handle associated with pid, mark it dead and record exit
409 * status. Finds all thread handles associated with this process
410 * handle, and marks those signalled too, with exitstatus '0'. It
411 * also drops the daemon's reference to the handle, and the thread
412 * pointed at by main_thread.
414 static void process_post_mortem (pid_t pid, int status)
416 gpointer process_handle;
417 struct _WapiHandle_process *process_handle_data;
419 process_handle=_wapi_search_handle (WAPI_HANDLE_PROCESS,
421 GUINT_TO_POINTER (pid),
422 (gpointer *)&process_handle_data,
424 if(process_handle==0) {
425 g_warning (G_GNUC_PRETTY_FUNCTION
426 ": Couldn't find handle for process %d!", pid);
428 /* Signal the handle. Don't use
429 * _wapi_handle_set_signal_state() unless we have
430 * process-shared pthread support.
433 g_message (G_GNUC_PRETTY_FUNCTION
434 ": Set process %d exitstatus to %d", pid,
435 WEXITSTATUS (status));
438 /* Technically WEXITSTATUS is only valid if the
439 * process exited normally, but I don't care if the
440 * process caught a signal or not.
442 process_handle_data->exitstatus=WEXITSTATUS (status);
443 _wapi_time_t_to_filetime (time (NULL),
444 &process_handle_data->exit_time);
446 #ifdef _POSIX_THREAD_PROCESS_SHARED
447 _wapi_handle_lock_handle (process_handle);
448 _wapi_handle_set_signal_state (process_handle, TRUE, TRUE);
449 _wapi_handle_unlock_handle (process_handle);
451 /* Just tweak the signal state directly. This is not
452 * recommended behaviour, but it works for processes
453 * because they can never become unsignalled. There
454 * are some nasty kludges in the handle waiting code
455 * to cope with missing condition signals for when
456 * process-shared pthread support is missing.
458 _wapi_shared_data->handles[GPOINTER_TO_UINT (process_handle)].signalled=TRUE;
459 #endif /* _POSIX_THREAD_PROCESS_SHARED */
462 /* Find all threads that have their process
463 * handle==process_handle. Ignore the return value, all the
464 * work will be done in the compare func
466 (void)_wapi_search_handle (WAPI_HANDLE_THREAD, process_thread_compare,
467 process_handle, NULL, NULL);
469 unref_handle (0, GPOINTER_TO_UINT (process_handle_data->main_thread));
470 unref_handle (0, GPOINTER_TO_UINT (process_handle));
473 static void process_died (void)
478 check_processes=FALSE;
481 g_message (G_GNUC_PRETTY_FUNCTION ": Reaping processes");
485 pid=waitpid (-1, &status, WNOHANG);
486 if(pid==0 || pid==-1) {
487 /* Finished waiting. I was checking pid==-1
488 * separately but was getting ECHILD when
489 * there were no more child processes (which
490 * doesnt seem to conform to the man page)
494 /* pid contains the ID of a dead process */
496 g_message (G_GNUC_PRETTY_FUNCTION ": process %d reaped", pid);
498 process_post_mortem (pid, status);
506 * @idx: idx into pollfds.
507 * @rest: Package to send
509 * Send a package to a client
511 static void send_reply (guint32 idx, WapiHandleResponse *resp)
514 _wapi_daemon_response (pollfds[idx].fd, resp);
519 * @idx: idx into pollfds.
520 * @type: type to init handle to
522 * Find a free handle and initialize it to 'type', increase refcnt and
523 * send back a reply to the client.
525 static void process_new (guint32 idx, WapiHandleType type)
528 WapiHandleResponse resp;
530 /* handle might be set to 0. This is handled at the client end */
531 handle=_wapi_handle_new_internal (type);
532 ref_handle (idx, handle);
535 g_message (G_GNUC_PRETTY_FUNCTION ": returning new handle 0x%x",
539 resp.type=WapiHandleResponseType_New;
540 resp.u.new.type=type;
541 resp.u.new.handle=handle;
543 send_reply (idx, &resp);
548 * @idx: idx into pollfds.
549 * @handle: handle no.
551 * Increase refcnt on a previously created handle and send back a
552 * response to the client.
554 static void process_open (guint32 idx, guint32 handle)
556 WapiHandleResponse resp;
557 struct _WapiHandleShared *shared=&_wapi_shared_data->handles[handle];
559 if(shared->type!=WAPI_HANDLE_UNUSED && handle!=0) {
560 ref_handle (idx, handle);
563 g_message (G_GNUC_PRETTY_FUNCTION
564 ": returning new handle 0x%x", handle);
567 resp.type=WapiHandleResponseType_Open;
568 resp.u.new.type=shared->type;
569 resp.u.new.handle=handle;
571 send_reply (idx, &resp);
576 resp.type=WapiHandleResponseType_Open;
579 send_reply (idx, &resp);
584 * @idx: idx into pollfds.
585 * @handle: handle no.
587 * Decrease refcnt on a previously created handle and send back a
588 * response to the client with notice of it being destroyed.
590 static void process_close (guint32 idx, guint32 handle)
592 WapiHandleResponse resp;
594 resp.type=WapiHandleResponseType_Close;
595 resp.u.close.destroy=unref_handle (idx, handle);
598 g_message (G_GNUC_PRETTY_FUNCTION ": unreffing handle 0x%x", handle);
601 send_reply (idx, &resp);
606 * @idx: idx into pollfds.
607 * @length: allocate this much scratch space
609 * Allocate some scratch space and send a reply to the client.
611 static void process_scratch (guint32 idx, guint32 length)
613 WapiHandleResponse resp;
615 resp.type=WapiHandleResponseType_Scratch;
616 resp.u.scratch.idx=_wapi_handle_scratch_store_internal (length);
619 g_message (G_GNUC_PRETTY_FUNCTION ": allocating scratch index 0x%x",
623 send_reply (idx, &resp);
627 * process_scratch_free:
628 * @idx: idx into pollfds.
629 * @scratch_idx: deallocate this scratch space
631 * Deallocate scratch space and send a reply to the client.
633 static void process_scratch_free (guint32 idx, guint32 scratch_idx)
635 WapiHandleResponse resp;
637 resp.type=WapiHandleResponseType_ScratchFree;
638 _wapi_handle_scratch_delete_internal (scratch_idx);
641 g_message (G_GNUC_PRETTY_FUNCTION ": deleting scratch index 0x%x",
645 send_reply (idx, &resp);
648 static void process_process_fork (guint32 idx,
649 WapiHandleRequest_ProcessFork process_fork,
652 WapiHandleResponse resp;
653 guint32 process_handle, thread_handle;
654 struct _WapiHandle_process *process_handle_data;
655 struct _WapiHandle_thread *thread_handle_data;
658 resp.type=WapiHandleResponseType_ProcessFork;
660 /* Create handles first, so the child process can store exec
661 * errors. Either handle might be set to 0, if this happens
662 * just reply to the client without bothering to fork. The
663 * client must check if either handle is 0 and take
664 * appropriate error handling action.
666 process_handle=_wapi_handle_new_internal (WAPI_HANDLE_PROCESS);
667 ref_handle (0, process_handle);
668 ref_handle (idx, process_handle);
670 thread_handle=_wapi_handle_new_internal (WAPI_HANDLE_THREAD);
671 ref_handle (0, thread_handle);
672 ref_handle (idx, thread_handle);
674 if(process_handle==0 || thread_handle==0) {
675 /* unref_handle() copes with the handle being 0 */
676 unref_handle (0, process_handle);
677 unref_handle (idx, process_handle);
678 unref_handle (0, thread_handle);
679 unref_handle (idx, thread_handle);
683 char *cmd=NULL, *args=NULL;
685 /* Get usable copies of the cmd and args now rather
686 * than in the child process. This is to prevent the
687 * race condition where the parent can return the
688 * reply to the client, which then promptly deletes
689 * the scratch data before the new process gets to see
692 cmd=_wapi_handle_scratch_lookup_as_string (process_fork.cmd);
693 if(process_fork.args!=0) {
694 args=_wapi_handle_scratch_lookup_as_string (process_fork.args);
698 g_message (G_GNUC_PRETTY_FUNCTION ": forking");
701 _wapi_lookup_handle (GUINT_TO_POINTER (process_handle),
703 (gpointer *)&process_handle_data, NULL);
705 _wapi_lookup_handle (GUINT_TO_POINTER (thread_handle),
707 (gpointer *)&thread_handle_data, NULL);
709 /* Fork, exec cmd with args and optional env, and
710 * return the handles with pid and blank thread id
714 process_handle_data->exec_errno=errno;
717 char **argv, *full_args;
721 /* should we detach from the process group?
722 * We're already running without a controlling
725 if(process_fork.inherit!=TRUE) {
726 /* Close all file descriptors */
729 /* Connect stdin, stdout and stderr */
735 g_message (G_GNUC_PRETTY_FUNCTION
736 ": exec()ing [%s] args [%s]", cmd, args);
740 full_args=g_strconcat (cmd, " ", args, NULL);
742 full_args=g_strdup (cmd);
744 ret=g_shell_parse_argv (full_args, NULL, &argv, &gerr);
749 /* FIXME: Could do something with the
752 process_handle_data->exec_errno=gerr->code;
760 while(argv[i]!=NULL) {
761 g_message ("arg %d: [%s]", i, argv[i]);
772 process_handle_data->exec_errno=errno;
778 process_handle_data->id=pid;
779 process_handle_data->main_thread=GUINT_TO_POINTER (thread_handle);
780 _wapi_time_t_to_filetime (time (NULL),
781 &process_handle_data->create_time);
783 /* FIXME: if env==0, inherit the env from the current
786 process_handle_data->env=process_fork.env;
788 thread_handle_data->process_handle=GUINT_TO_POINTER (process_handle);
790 resp.u.process_fork.pid=pid;
793 resp.u.process_fork.process_handle=process_handle;
794 resp.u.process_fork.thread_handle=thread_handle;
796 send_reply (idx, &resp);
801 * @idx: idx into pollfds.
803 * Read a message (A WapiHandleRequest) from a client and dispatch
804 * whatever it wants to the process_* calls.
806 static void read_message (guint32 idx)
808 WapiHandleRequest req;
809 int fds[3]={0, 1, 2};
810 gboolean has_fds=FALSE;
813 _wapi_daemon_request (pollfds[idx].fd, &req, fds, &has_fds);
815 case WapiHandleRequestType_New:
816 process_new (idx, req.u.new.type);
818 case WapiHandleRequestType_Open:
820 g_assert(req.u.open.handle < _WAPI_MAX_HANDLES);
822 process_open (idx, req.u.open.handle);
824 case WapiHandleRequestType_Close:
826 g_assert(req.u.close.handle < _WAPI_MAX_HANDLES);
828 process_close (idx, req.u.close.handle);
830 case WapiHandleRequestType_Scratch:
831 process_scratch (idx, req.u.scratch.length);
833 case WapiHandleRequestType_ScratchFree:
834 process_scratch_free (idx, req.u.scratch_free.idx);
836 case WapiHandleRequestType_ProcessFork:
837 process_process_fork (idx, req.u.process_fork, fds);
839 case WapiHandleRequestType_Error:
842 /* Catch bogus requests */
843 /* FIXME: call rem_fd? */
849 g_message (G_GNUC_PRETTY_FUNCTION ": closing %d", fds[0]);
850 g_message (G_GNUC_PRETTY_FUNCTION ": closing %d", fds[1]);
851 g_message (G_GNUC_PRETTY_FUNCTION ": closing %d", fds[2]);
863 * Open socket, create shared mem segment and begin listening for
866 void _wapi_daemon_main(void)
868 struct sockaddr_un main_socket_address;
872 g_message ("Starting up...");
877 main_sock=socket(PF_UNIX, SOCK_STREAM, 0);
879 main_socket_address.sun_family=AF_UNIX;
880 memcpy(main_socket_address.sun_path, _wapi_shared_data->daemon,
881 MONO_SIZEOF_SUNPATH);
883 ret=bind(main_sock, (struct sockaddr *)&main_socket_address,
884 sizeof(struct sockaddr_un));
886 g_critical ("bind failed: %s", strerror (errno));
887 _wapi_shared_data->daemon_running=DAEMON_DIED_AT_STARTUP;
895 ret=listen(main_sock, 5);
897 g_critical ("listen failed: %s", strerror (errno));
898 _wapi_shared_data->daemon_running=DAEMON_DIED_AT_STARTUP;
903 g_message("listening");
908 /* We're finished setting up, let everyone else know we're
909 * ready. From now on, it's up to us to delete the shared
910 * memory segment when appropriate.
912 _wapi_shared_data->daemon_running=DAEMON_RUNNING;
917 if(check_processes==TRUE) {
922 g_message ("polling");
925 /* Block until something happens */
926 ret=poll(pollfds, nfds, -1);
927 if(ret==-1 && errno!=EINTR) {
928 g_critical ("poll error: %s", strerror (errno));
933 for(i=0; i<nfds; i++) {
934 if(((pollfds[i].revents&POLLHUP)==POLLHUP) ||
935 ((pollfds[i].revents&POLLERR)==POLLERR) ||
936 ((pollfds[i].revents&POLLNVAL)==POLLNVAL)) {
938 g_message ("fd[%d] %d error", i,
942 } else if((pollfds[i].revents&POLLIN)==POLLIN) {
943 /* If a client is connecting, accept
944 * it and begin listening to that
945 * socket too. Otherwise it must be a
946 * client we already have that wants
949 /* FIXME: Make sure i==0 too? */
950 if(pollfds[i].fd==main_sock) {
952 struct sockaddr addr;
953 socklen_t addrlen=sizeof(struct sockaddr);
954 newsock=accept(main_sock, &addr,
957 g_critical("accept error: %s",
963 g_message ("accept returning %d",
969 g_message ("reading data on fd %d",