Flush (work in progress)
[mono.git] / mono / io-layer / daemon.c
1 /*
2  * daemon.c:  The handle daemon
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <signal.h>
21 #include <sys/wait.h>
22 #include <string.h>
23 #include <sys/time.h>
24
25 #ifdef HAVE_POLL
26 #include <sys/poll.h>
27 #endif
28
29 #include <mono/io-layer/io-layer.h>
30 #include <mono/io-layer/handles-private.h>
31 #include <mono/io-layer/wapi-private.h>
32 #include <mono/io-layer/daemon-messages.h>
33 #include <mono/io-layer/timefuncs-private.h>
34 #include <mono/io-layer/daemon-private.h>
35 #include <mono/io-layer/socket-wrappers.h>
36
37 #define LOGDEBUG(...)
38 #undef DEBUG
39 // #define LOGDEBUG(...) g_message(__VA_ARGS__)
40
41 /* The shared thread codepath doesn't seem to work yet... */
42 #undef _POSIX_THREAD_PROCESS_SHARED
43
44 /* Keep track of the number of clients */
45 static int nfds=0;
46
47 /* Arrays to keep track of channel data for the 
48  * daemon and clients indexed by file descriptor
49  * value.
50  */
51
52 typedef struct _channel_data {
53         int io_source; /* the ID given back by g_io_add_watch */
54         guint32 *open_handles; /* array of open handles for this client */
55 } ChannelData;
56
57 static ChannelData *daemon_channel_data=NULL;
58 static ChannelData *channels=NULL;
59 static int channels_length=0;
60
61 /* The socket which we listen to new connections on */
62 static int main_sock;
63
64 /* Set to TRUE by the SIGCHLD signal handler */
65 static volatile gboolean check_processes=FALSE;
66
67 /* The file_share_hash is used to emulate the windows file sharing mode */
68 typedef struct _share_key
69 {
70         dev_t device;
71         ino_t inode;
72 } ShareKey;
73
74 typedef struct _share_data
75 {
76         guint32 sharemode;
77         guint32 access;
78 } ShareData;
79
80 static GHashTable *file_share_hash = NULL;
81
82 static gboolean fd_activity (GIOChannel *channel, GIOCondition condition,
83                              gpointer data);
84 static void check_sharing (dev_t device, ino_t inode);
85
86 /* Deletes the shared memory segment.  If we're exiting on error,
87  * clients will get EPIPEs.
88  */
89 static void cleanup (void)
90 {
91         int i;
92         
93 #ifdef NEED_LINK_UNLINK
94         unlink(_wapi_shared_data[0]->daemon);
95 #endif 
96         for(i=1; i<_wapi_shared_data[0]->num_segments; i++) {
97                 unlink (_wapi_shm_file (WAPI_SHM_DATA, i));
98         }
99         unlink (_wapi_shm_file (WAPI_SHM_DATA, 0));
100         
101         /* There's only one scratch file */
102         unlink (_wapi_shm_file (WAPI_SHM_SCRATCH, 0));
103 }
104
105 /* If there is only one socket, and no child processes, we can exit.
106  * We test for child processes by counting handle references held by
107  * the daemon.
108  */
109 static void maybe_exit (void)
110 {
111         guint32 i;
112
113         LOGDEBUG ("%s: Seeing if we should exit", __func__);
114
115         if(nfds>1) {
116                 LOGDEBUG ("%s: Still got clients", __func__);
117                 return;
118         }
119
120         /* Prevent new clients from connecting... */
121         _wapi_shared_data[0]->daemon_running=DAEMON_CLOSING;
122
123         for(i=0;
124             i<_wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT;
125             i++) {
126                 if(daemon_channel_data->open_handles[i]>0) {
127                         LOGDEBUG ("%s: Still got handle references", __func__);
128                         _wapi_shared_data[0]->daemon_running=DAEMON_RUNNING;
129                         return;
130                 }
131         }
132         
133 #ifdef HAVE_POLL
134         /* Last check, make sure no client came along while we were
135          * checking the handle lists.
136          *
137          * Use poll() directly here, as glib doesn't seem to have any
138          * exposed way of seeing if a file descriptor is ready
139          * (g_io_channel_get_buffer_condition() isn't it.)
140          *
141          * Crappy systems that don't have poll() will just have to
142          * lump it (for them there is still the very slight chance
143          * that someone tried to connect just as the DAEMON_CLOSING
144          * flag was being set.)
145          */
146         {
147                 struct pollfd fds[1];
148                 
149                 fds[0].fd=main_sock;
150                 fds[0].events=POLLIN;
151                 fds[0].revents=0;
152                 
153                 LOGDEBUG ("%s: Last connect check", __func__);
154
155                 if(poll (fds, 1, 0)>0) {
156                         /* Someone did connect, so carry on running */
157                         LOGDEBUG ("%s: Someone connected", __func__);
158
159                         _wapi_shared_data[0]->daemon_running=DAEMON_RUNNING;
160                         return;
161                 }
162         }
163 #endif
164         
165         LOGDEBUG ("%s: Byebye", __func__);
166         
167         cleanup ();
168         exit (0);
169 }
170
171 /*
172  * signal_handler:
173  * @unused: unused
174  *
175  * Called if daemon receives a SIGTERM or SIGINT
176  */
177 static void signal_handler (int signo)
178 {
179         LOGDEBUG ("%s: daemon received signal %d", __func__, signo);
180
181         cleanup ();
182         exit (-1);
183 }
184
185 /*
186  * sigchld_handler:
187  * @unused: unused
188  *
189  * Called if daemon receives a SIGCHLD, and notes that a process needs
190  * to be wait()ed for.
191  */
192 static void sigchld_handler (int unused)
193 {
194         /* Notice that a child process died */
195         check_processes=TRUE;
196 }
197
198 static guint sharedata_hash (gconstpointer key)
199 {
200         ShareKey *sharekey = (ShareKey *)key;
201         
202         return(g_int_hash (&(sharekey->inode)));
203 }
204
205 static gboolean sharedata_equal (gconstpointer a, gconstpointer b)
206 {
207         ShareKey *share_a = (ShareKey *)a;
208         ShareKey *share_b = (ShareKey *)b;
209         
210         return(share_a->device == share_b->device &&
211                share_a->inode == share_b->inode);
212 }
213
214 /* Catch this here rather than corrupt the shared data at runtime */
215 #if MONO_SIZEOF_SUNPATH==0
216 #error configure failed to discover size of unix socket path
217 #endif
218
219 /*
220  * startup:
221  *
222  * Bind signals, attach to shared memory and set up any internal data
223  * structures needed.
224  */
225 static void startup (void)
226 {
227         struct sigaction sa;
228         
229         sa.sa_handler=signal_handler;
230         sigemptyset (&sa.sa_mask);
231         sa.sa_flags=0;
232         sigaction (SIGINT, &sa, NULL);
233         sigaction (SIGTERM, &sa, NULL);
234         
235 #ifndef HAVE_MSG_NOSIGNAL
236         sa.sa_handler=SIG_IGN;
237         sigaction (SIGPIPE, &sa, NULL);
238 #endif
239
240         sa.sa_handler=sigchld_handler;
241         sa.sa_flags=SA_NOCLDSTOP;
242         sigaction (SIGCHLD, &sa, NULL);
243         
244 #ifdef NEED_LINK_UNLINK
245         /* Here's a more portable method... */
246         snprintf (_wapi_shared_data[0]->daemon, MONO_SIZEOF_SUNPATH-1,
247                   "/tmp/mono-handle-daemon-%d-%ld-%ld", getuid (), random (),
248                   time (NULL));
249 #else
250         /* Leave the first byte NULL so we create the socket in the
251          * abstrace namespace, not on the filesystem.  (Lets see how
252          * portable _that_ is :)
253          *
254          * The name is intended to be unique, not cryptographically
255          * secure...
256          */
257         snprintf (_wapi_shared_data[0]->daemon+1, MONO_SIZEOF_SUNPATH-2,
258                   "mono-handle-daemon-%d-%d-%ld", getuid (), getpid (),
259                   time (NULL));
260 #endif
261
262         file_share_hash = g_hash_table_new_full (sharedata_hash,
263                                                  sharedata_equal, g_free,
264                                                  g_free);
265 }
266
267
268 /*
269  * ref_handle:
270  * @channel_data: Channel data for calling client
271  * @handle: handle to inc refcnt
272  *
273  * Increase ref count of handle for the calling client.  Handle 0 is
274  * ignored.
275  */
276 static void ref_handle (ChannelData *channel_data, guint32 handle)
277 {
278         guint32 segment, idx;
279         
280         if(handle==0) {
281                 return;
282         }
283         
284         _wapi_handle_segment (GUINT_TO_POINTER (handle), &segment, &idx);
285         
286         _wapi_shared_data[segment]->handles[idx].ref++;
287         channel_data->open_handles[handle]++;
288         
289         LOGDEBUG ("%s: handle 0x%x ref now %d (%d this process)", __func__, handle,
290                   _wapi_shared_data[segment]->handles[idx].ref,
291                   channel_data->open_handles[handle]);
292 }
293
294 /*
295  * unref_handle:
296  * @channel_data: Channel data for calling client
297  * @handle: handle to inc refcnt
298  *
299  * Decrease ref count of handle for the calling client. If global ref
300  * count reaches 0 it is free'ed. Return TRUE if the local ref count
301  * is 0. Handle 0 is ignored.
302  */
303 static gboolean unref_handle (ChannelData *channel_data, guint32 handle)
304 {
305         gboolean destroy=FALSE;
306         guint32 segment, idx;
307         
308         if(handle==0) {
309                 return(FALSE);
310         }
311         
312         if (channel_data->open_handles[handle] == 0) {
313                 g_warning("%s: unref on %d called when ref was already 0", __func__, handle);
314                 return TRUE;
315         }
316
317         _wapi_handle_segment (GUINT_TO_POINTER (handle), &segment, &idx);
318         
319         _wapi_shared_data[segment]->handles[idx].ref--;
320         channel_data->open_handles[handle]--;
321         
322         LOGDEBUG ("%s: handle 0x%x ref now %d (%d this process)", __func__, handle,
323                    _wapi_shared_data[segment]->handles[idx].ref,
324                    channel_data->open_handles[handle]);
325
326         if (_wapi_shared_data[segment]->handles[idx].ref == 0) {
327                 gboolean was_file;
328                 dev_t device = 0;
329                 ino_t inode = 0;
330                 
331                 /* This client has released the handle */
332                 destroy=TRUE;
333         
334                 if (channel_data->open_handles[handle]!=0) {
335                         g_warning ("%s: per-process open_handles mismatch, set to %d, should be 0",__func__, channel_data->open_handles[handle]);
336                 }
337                 
338                 LOGDEBUG ("%s: Destroying handle 0x%x", __func__, handle);
339
340                 /* if this was a file handle, save the device and
341                  * inode numbers so we can scan the share info data
342                  * later to see if the last handle to a file has been
343                  * closed, and delete the data if so.
344                  */
345                 was_file = (_wapi_shared_data[segment]->handles[idx].type == WAPI_HANDLE_FILE);
346                 if (was_file) {
347                         struct _WapiHandle_file *file_handle;
348                         gboolean ok;
349                         
350                         ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle),
351                                                   WAPI_HANDLE_FILE,
352                                                   (gpointer *)&file_handle,
353                                                   NULL);
354                         if (ok == FALSE) {
355                                 g_warning ("%s: error looking up file handle %x", __func__, handle);
356                         } else {
357                                 device = file_handle->device;
358                                 inode = file_handle->inode;
359                         }
360                 }
361                 
362                 _wapi_handle_ops_close_shared (GUINT_TO_POINTER (handle));
363                 
364 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
365                 mono_mutex_destroy (&_wapi_shared_data[segment]->handles[idx].signal_mutex);
366                 pthread_cond_destroy (&_wapi_shared_data[segment]->handles[idx].signal_cond);
367 #endif
368
369                 memset (&_wapi_shared_data[segment]->handles[idx].u, '\0', sizeof(_wapi_shared_data[segment]->handles[idx].u));
370                 _wapi_shared_data[segment]->handles[idx].type=WAPI_HANDLE_UNUSED;
371
372                 if (was_file) {
373                         check_sharing (device, inode);
374                 }
375         }
376
377         if(channel_data == daemon_channel_data) {
378                 /* The daemon released a reference, so see if it's
379                  * ready to exit
380                  */
381                 maybe_exit ();
382         }
383         
384         return(destroy);
385 }
386
387 /*
388  * add_fd:
389  * @fd: Filehandle to add
390  *
391  * Create a new GIOChannel, and add it to the main loop event sources.
392  */
393 static void add_fd(int fd, GMainContext *context)
394 {
395         GIOChannel *io_channel;
396         GSource *source;
397         guint32 *refs;
398         
399         io_channel=g_io_channel_unix_new (fd);
400         
401         /* Turn off all encoding and buffering crap */
402         g_io_channel_set_encoding (io_channel, NULL, NULL);
403         g_io_channel_set_buffered (io_channel, FALSE);
404         
405         refs=g_new0 (guint32,_wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT);
406
407         if(fd>=channels_length) {
408                 /* Add a bit of padding, so we dont resize for _every_
409                  * new connection
410                  */
411                 int old_len=channels_length * sizeof(ChannelData);
412                 
413                 channels_length=fd+10;
414                 if(channels==NULL) {
415                         channels=g_new0 (ChannelData, channels_length);
416                         /* We rely on the daemon channel being created first.
417                          * That's safe, because every other channel is the
418                          * result of an accept() on the daemon channel.
419                          */
420                         daemon_channel_data = &channels[fd];
421                 } else {
422                         int daemon_index=daemon_channel_data - channels;
423
424                         /* Can't use g_renew here, because the unused
425                          * elements must be NULL and g_renew doesn't
426                          * initialise the memory it returns
427                          */
428                         channels=_wapi_g_renew0 (channels, old_len, channels_length * sizeof(ChannelData));
429                         daemon_channel_data = channels + daemon_index;
430                 }
431
432         }
433
434         channels[fd].open_handles=refs;
435
436         source = g_io_create_watch (io_channel, 
437                                     G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL);
438         g_source_set_callback (source, (GSourceFunc)fd_activity, 
439                                context, NULL);
440         channels[fd].io_source=g_source_attach (source, context);
441         g_source_unref (source);
442
443         nfds++;
444 }
445
446 /*
447  * rem_fd:
448  * @channel: GIOChannel to close
449  *
450  * Closes the IO channel. Closes all handles that it may have open. If
451  * only main_sock is left, the daemon is shut down.
452  */
453 static void rem_fd(GIOChannel *channel, ChannelData *channel_data)
454 {
455         guint32 handle_count;
456         int i, j, fd;
457         
458         fd=g_io_channel_unix_get_fd (channel);
459         
460         if(fd == main_sock) {
461                 /* We shouldn't be deleting the daemon's fd */
462                 g_warning ("%s: Deleting daemon fd!", __func__);
463                 cleanup ();
464                 exit (-1);
465         }
466         
467         LOGDEBUG ("%s: Removing client fd %d", __func__, fd);
468
469         if (channel_data->io_source == 0) {
470                 LOGDEBUG ("%s: channel already closed for fd %d", __func__, fd);
471                 return;
472         }
473
474
475         g_io_channel_shutdown (channel, TRUE, NULL);
476         g_source_remove (channel_data->io_source);
477         g_io_channel_unref (channel);
478
479         for(i=0;
480             i<_wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT;
481             i++) {
482                 handle_count=channel_data->open_handles[i];
483                 
484                 for(j=0; j<handle_count; j++) {
485                         LOGDEBUG ("%s: closing handle 0x%x for client at index %d", __func__, i, g_io_channel_unix_get_fd (channel));
486                         /* Ignore the hint to the client to destroy
487                          * the handle private data
488                          */
489                         unref_handle (channel_data, i);
490                 }
491         }
492         
493         g_free (channel_data->open_handles);
494         channel_data->open_handles=NULL;
495         channel_data->io_source=0;
496         
497         nfds--;
498         if(nfds==1) {
499                 /* Just the master socket left, so see if we can
500                  * cleanup and exit
501                  */
502                 maybe_exit ();
503         }
504 }
505
506 static void sharemode_set (dev_t device, ino_t inode, guint32 sharemode,
507                            guint32 access)
508 {
509         ShareKey *sharekey;
510         ShareData *sharedata;
511         
512         sharekey = g_new (ShareKey, 1);
513         sharekey->device = device;
514         sharekey->inode = inode;
515
516         sharedata = g_new (ShareData, 1);
517         sharedata->sharemode = sharemode;
518         sharedata->access = access;
519         
520         /* Setting share mode to include all access bits is really
521          * removing the share info
522          */
523         if (sharemode == (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE)) {
524                 g_hash_table_remove (file_share_hash, sharekey);
525         } else {
526                 g_hash_table_insert (file_share_hash, sharekey, sharedata);
527         }
528 }
529
530 static gboolean sharemode_get (dev_t device, ino_t inode, guint32 *sharemode,
531                                guint32 *access)
532 {
533         ShareKey sharekey;
534         ShareData *sharedata;
535         
536         sharekey.device = device;
537         sharekey.inode = inode;
538         
539         sharedata = (ShareData *)g_hash_table_lookup (file_share_hash,
540                                                        &sharekey);
541         if (sharedata == NULL) {
542                 return(FALSE);
543         }
544         
545         *sharemode = sharedata->sharemode;
546         *access = sharedata->access;
547         
548         return(TRUE);
549 }
550
551 static gboolean share_compare (gpointer handle, gpointer user_data)
552 {
553         struct _WapiHandle_file *file_handle;
554         gboolean ok;
555         ShareKey *sharekey = (ShareKey *)user_data;
556         
557         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
558                                   (gpointer *)&file_handle, NULL);
559         if (ok == FALSE) {
560                 g_warning ("%s: error looking up file handle %p", __func__, handle);
561                 return(FALSE);
562         }
563         
564         if (file_handle->device == sharekey->device &&
565             file_handle->inode == sharekey->inode) {
566                 LOGDEBUG ("%s: found one, handle %p", __func__, handle);
567                 return(TRUE);
568         } else {
569                 return(FALSE);
570         }
571 }
572
573 static void check_sharing (dev_t device, ino_t inode)
574 {
575         ShareKey sharekey;
576         gpointer file_handle;
577         
578         LOGDEBUG ("%s: Checking if anything has (dev 0x%llx, inode %lld) still open", __func__, device, inode);
579
580         sharekey.device = device;
581         sharekey.inode = inode;
582         
583         file_handle = _wapi_search_handle (WAPI_HANDLE_FILE, share_compare,
584                                            &sharekey, NULL, NULL);
585
586         if (file_handle == NULL) {
587                 /* Delete this share info, as the last handle to it
588                  * has been closed
589                  */
590                 LOGDEBUG ("%s: Deleting share data for (dev 0x%llx inode %lld)", __func__, device, inode);
591                 
592                 g_hash_table_remove (file_share_hash, &sharekey);
593         }
594 }
595
596 static gboolean process_compare (gpointer handle, gpointer user_data)
597 {
598         struct _WapiHandle_process *process_handle;
599         gboolean ok;
600         pid_t pid;
601         guint32 segment, idx;
602         
603         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
604                                 (gpointer *)&process_handle, NULL);
605         if(ok==FALSE) {
606                 g_warning ("%s: error looking up process handle %p", __func__, handle);
607                 return(FALSE);
608         }
609
610         _wapi_handle_segment (handle, &segment, &idx);
611         if (_wapi_shared_data[segment]->handles[idx].signalled) {
612                 return(FALSE);
613         }
614
615         pid=GPOINTER_TO_UINT (user_data);
616         if(process_handle->id==pid) {
617                 return(TRUE);
618         } else {
619                 return(FALSE);
620         }
621 }
622
623 static gboolean process_thread_compare (gpointer handle, gpointer user_data)
624 {
625         struct _WapiHandle_thread *thread_handle;
626         gboolean ok;
627         guint32 segment, idx;
628         
629         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
630                                 (gpointer *)&thread_handle, NULL);
631         if(ok==FALSE) {
632                 g_warning ("%s: error looking up thread handle %p", __func__, handle);
633                 return(FALSE);
634         }
635
636         if(thread_handle->process_handle==user_data) {
637                 /* Signal the handle.  Don't use
638                  * _wapi_handle_set_signal_state() unless we have
639                  * process-shared pthread support.
640                  */
641                 LOGDEBUG ("%s: Set thread handle %p signalled, because its process died", __func__, handle);
642
643                 thread_handle->exitstatus=0;
644
645 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
646                 _wapi_handle_lock_handle (handle);
647                 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
648                 _wapi_handle_unlock_handle (handle);
649 #else
650                 /* Just tweak the signal state directly.  This is not
651                  * recommended behaviour, but it works for threads
652                  * because they can never become unsignalled.  There
653                  * are some nasty kludges in the handle waiting code
654                  * to cope with missing condition signals for when
655                  * process-shared pthread support is missing.
656                  */
657                 _wapi_handle_segment (handle, &segment, &idx);
658                 _wapi_shared_data[segment]->handles[idx].signalled=TRUE;
659 #endif /* _POSIX_THREAD_PROCESS_SHARED */
660         }
661         
662         /* Return false to keep searching */
663         return(FALSE);
664 }
665
666 /* Find the handle associated with pid, mark it dead and record exit
667  * status.  Finds all thread handles associated with this process
668  * handle, and marks those signalled too, with exitstatus '0'.  It
669  * also drops the daemon's reference to the handle, and the thread
670  * pointed at by main_thread.
671  */
672 static void process_post_mortem (pid_t pid, int status)
673 {
674         gpointer process_handle;
675         struct _WapiHandle_process *process_handle_data;
676         guint32 segment, idx;
677         
678         process_handle=_wapi_search_handle (WAPI_HANDLE_PROCESS,
679                                             process_compare,
680                                             GUINT_TO_POINTER (pid),
681                                             (gpointer *)&process_handle_data,
682                                             NULL);
683         if(process_handle==0) {
684                 /*
685                  * This may happen if we use Process.EnableRaisingEvents +
686                  * process.Exited event and the parent has finished.
687                  */
688                 LOGDEBUG ("%s: Couldn't find handle for process %d!", __func__, pid);
689         } else {
690                 /* Signal the handle.  Don't use
691                  * _wapi_handle_set_signal_state() unless we have
692                  * process-shared pthread support.
693                  */
694                 struct timeval tv;
695                 
696                 LOGDEBUG ("%s: Set process %d exitstatus to %d", __func__, pid,
697                            WEXITSTATUS (status));
698                 
699                 /* If the child terminated due to the receipt of a signal,
700                  * the exit status must be based on WTERMSIG, since WEXITSTATUS
701                  * returns 0 in this case.
702                  */
703                 if (WIFSIGNALED(status))
704                         process_handle_data->exitstatus=128 + WTERMSIG (status);
705                 else
706                         process_handle_data->exitstatus=WEXITSTATUS (status);
707
708                 /* Ignore errors */
709                 gettimeofday (&tv, NULL);
710                 _wapi_timeval_to_filetime (&tv,
711                                            &process_handle_data->exit_time);
712
713 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
714                 _wapi_handle_lock_handle (process_handle);
715                 _wapi_handle_set_signal_state (process_handle, TRUE, TRUE);
716                 _wapi_handle_unlock_handle (process_handle);
717 #else
718                 /* Just tweak the signal state directly.  This is not
719                  * recommended behaviour, but it works for processes
720                  * because they can never become unsignalled.  There
721                  * are some nasty kludges in the handle waiting code
722                  * to cope with missing condition signals for when
723                  * process-shared pthread support is missing.
724                  */
725                 _wapi_handle_segment (process_handle, &segment, &idx);
726                 _wapi_shared_data[segment]->handles[idx].signalled=TRUE;
727 #endif /* _POSIX_THREAD_PROCESS_SHARED */
728         }
729
730         /* Find all threads that have their process
731          * handle==process_handle.  Ignore the return value, all the
732          * work will be done in the compare func
733          */
734         (void)_wapi_search_handle (WAPI_HANDLE_THREAD, process_thread_compare,
735                                    process_handle, NULL, NULL);
736
737         unref_handle (daemon_channel_data,
738                       GPOINTER_TO_UINT (process_handle_data->main_thread));
739         unref_handle (daemon_channel_data, GPOINTER_TO_UINT (process_handle));
740 }
741
742 static void process_died (void)
743 {
744         int status;
745         pid_t pid;
746         
747         check_processes=FALSE;
748
749         LOGDEBUG ("%s: Reaping processes", __func__);
750
751         while(TRUE) {
752                 pid=waitpid (-1, &status, WNOHANG);
753                 if(pid==0 || pid==-1) {
754                         /* Finished waiting.  I was checking pid==-1
755                          * separately but was getting ECHILD when
756                          * there were no more child processes (which
757                          * doesnt seem to conform to the man page)
758                          */
759                         return;
760                 } else {
761                         /* pid contains the ID of a dead process */
762                         LOGDEBUG ( "%s: process %d reaped", __func__, pid);
763                         process_post_mortem (pid, status);
764                 }
765         }
766 }
767
768
769 /*
770  * send_reply:
771  * @channel: channel to send reply to
772  * @resp: Package to send
773  *
774  * Send a package to a client
775  */
776 static void send_reply (GIOChannel *channel, WapiHandleResponse *resp)
777 {
778         /* send message */
779         _wapi_daemon_response (g_io_channel_unix_get_fd (channel), resp);
780 }
781
782 static guint32 new_handle_with_shared_check (WapiHandleType type)
783 {
784         guint32 handle = 0;
785
786         while ((handle = _wapi_handle_new_internal (type)) == 0) {
787                 /* Try and allocate a new shared segment, and have
788                  * another go
789                  */
790                 guint32 segment=_wapi_shared_data[0]->num_segments;
791                 int i;
792                 
793                 _wapi_handle_ensure_mapped (segment);
794                 if(_wapi_shared_data[segment]!=NULL) {
795                         /* Got a new segment */
796                         gulong old_len, new_len;
797                         
798                         old_len=_wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT * sizeof(guint32);
799                         _wapi_shared_data[0]->num_segments++;
800                         new_len=_wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT * sizeof(guint32);
801
802                         /* Need to expand all the handle reference
803                          * count arrays
804                          */
805
806                         for(i=0; i<channels_length; i++) {
807                                 if(channels[i].open_handles!=NULL) {
808                                         channels[i].open_handles=_wapi_g_renew0 (channels[i].open_handles, old_len, new_len);
809                                 }
810                         }
811                 } else {
812                         /* Map failed.  Just return 0 meaning "out of
813                          * handles"
814                          */
815                         break;
816                 }
817         }
818         
819         return(handle);
820 }
821
822 /*
823  * process_new:
824  * @channel: The client making the request
825  * @channel_data: Our data for this channel
826  * @type: type to init handle to
827  *
828  * Find a free handle and initialize it to 'type', increase refcnt and
829  * send back a reply to the client.
830  */
831 static void process_new (GIOChannel *channel, ChannelData *channel_data,
832                          WapiHandleType type)
833 {
834         guint32 handle;
835         WapiHandleResponse resp={0};
836         
837         handle = new_handle_with_shared_check (type);
838         
839         /* handle might still be set to 0.  This is handled at the
840          * client end
841          */
842
843         ref_handle (channel_data, handle);
844
845         LOGDEBUG ("%s: returning new handle 0x%x", __func__, handle);
846
847         resp.type=WapiHandleResponseType_New;
848         resp.u.new.type=type;
849         resp.u.new.handle=handle;
850                         
851         send_reply (channel, &resp);
852 }
853
854 /*
855  * process_open:
856  * @channel: The client making the request
857  * @channel_data: Our data for this channel
858  * @handle: handle no.
859  *
860  * Increase refcnt on a previously created handle and send back a
861  * response to the client.
862  */
863 static void process_open (GIOChannel *channel, ChannelData *channel_data,
864                           guint32 handle)
865 {
866         WapiHandleResponse resp={0};
867         guint32 segment, idx;
868         struct _WapiHandleShared *shared;
869
870         _wapi_handle_segment (GUINT_TO_POINTER (handle), &segment, &idx);
871         shared=&_wapi_shared_data[segment]->handles[idx];
872                 
873         if(shared->type!=WAPI_HANDLE_UNUSED && handle!=0) {
874                 ref_handle (channel_data, handle);
875
876                 LOGDEBUG ("%s: returning new handle 0x%x", __func__, handle);
877
878                 resp.type=WapiHandleResponseType_Open;
879                 resp.u.new.type=shared->type;
880                 resp.u.new.handle=handle;
881                         
882                 send_reply (channel, &resp);
883
884                 return;
885         }
886
887         resp.type=WapiHandleResponseType_Open;
888         resp.u.new.handle=0;
889                         
890         send_reply (channel, &resp);
891 }
892
893 /*
894  * process_close:
895  * @channel: The client making the request
896  * @channel_data: Our data for this channel
897  * @handle: handle no.
898  *
899  * Decrease refcnt on a previously created handle and send back a
900  * response to the client with notice of it being destroyed.
901  */
902 static void process_close (GIOChannel *channel, ChannelData *channel_data,
903                            guint32 handle)
904 {
905         WapiHandleResponse resp={0};
906         
907         resp.type=WapiHandleResponseType_Close;
908         resp.u.close.destroy=unref_handle (channel_data, handle);
909
910         LOGDEBUG ("%s: unreffing handle 0x%x", __func__, handle);
911
912         send_reply (channel, &resp);
913 }
914
915 /*
916  * process_scratch:
917  * @channel: The client making the request
918  * @length: allocate this much scratch space
919  *
920  * Allocate some scratch space and send a reply to the client.
921  */
922 static void process_scratch (GIOChannel *channel, guint32 length)
923 {
924         WapiHandleResponse resp={0};
925         
926         resp.type=WapiHandleResponseType_Scratch;
927         resp.u.scratch.idx=_wapi_handle_scratch_store_internal (length, &resp.u.scratch.remap);
928
929         LOGDEBUG ("%s: allocating scratch index 0x%x", __func__, resp.u.scratch.idx);
930                         
931         send_reply (channel, &resp);
932 }
933
934 /*
935  * process_scratch_free:
936  * @channel: The client making the request
937  * @scratch_idx: deallocate this scratch space
938  *
939  * Deallocate scratch space and send a reply to the client.
940  */
941 static void process_scratch_free (GIOChannel *channel, guint32 scratch_idx)
942 {
943         WapiHandleResponse resp={0};
944         
945         resp.type=WapiHandleResponseType_ScratchFree;
946         _wapi_handle_scratch_delete_internal (scratch_idx);
947
948         LOGDEBUG ("%s: deleting scratch index 0x%x", __func__, scratch_idx);
949                         
950         send_reply (channel, &resp);
951 }
952
953 /*
954  * process_process_kill:
955  * @channel: The client making the request
956  * @process_kill: pid and signal to send to the pid.
957  *
958  * Sends the specified signal to the process.
959  */
960 static void
961 process_process_kill (GIOChannel *channel,
962                       WapiHandleRequest_ProcessKill process_kill)
963 {
964         WapiHandleResponse resp = {0};
965
966         resp.type = WapiHandleResponseType_ProcessKill;
967
968         LOGDEBUG ("%s: kill (%d, %d)", __func__, process_kill.pid, process_kill.signo);
969
970         if (kill (process_kill.pid, process_kill.signo) == -1) {
971                 resp.u.process_kill.err = errno;
972                 LOGDEBUG ("%s: kill (%d, %d) failed: %d", __func__, process_kill.pid, process_kill.signo, resp.u.process_kill.err);
973         }
974
975         send_reply (channel, &resp);
976 }
977
978 /*
979  * process_process_fork:
980  * @channel: The client making the request
981  * @process_fork: Describes the process to fork
982  * @fds: stdin, stdout, and stderr for the new process
983  *
984  * Forks a new process, and returns the process and thread data to the
985  * client.
986  */
987 static void process_process_fork (GIOChannel *channel, ChannelData *channel_data,
988                                   WapiHandleRequest_ProcessFork process_fork,
989                                   int *fds)
990 {
991         WapiHandleResponse resp={0};
992         guint32 process_handle, thread_handle;
993         struct _WapiHandle_process *process_handle_data;
994         struct _WapiHandle_thread *thread_handle_data;
995         pid_t pid = 0;
996         
997         resp.type=WapiHandleResponseType_ProcessFork;
998         
999         /* Create handles first, so the child process can store exec
1000          * errors.  Either handle might be set to 0, if this happens
1001          * just reply to the client without bothering to fork.  The
1002          * client must check if either handle is 0 and take
1003          * appropriate error handling action.
1004          */
1005         process_handle = new_handle_with_shared_check (WAPI_HANDLE_PROCESS);
1006         ref_handle (daemon_channel_data, process_handle);
1007         ref_handle (channel_data, process_handle);
1008         
1009         thread_handle = new_handle_with_shared_check (WAPI_HANDLE_THREAD);
1010         ref_handle (daemon_channel_data, thread_handle);
1011         ref_handle (channel_data, thread_handle);
1012         
1013         if(process_handle==0 || thread_handle==0) {
1014                 /* unref_handle() copes with the handle being 0 */
1015                 unref_handle (daemon_channel_data, process_handle);
1016                 unref_handle (channel_data, process_handle);
1017                 unref_handle (daemon_channel_data, thread_handle);
1018                 unref_handle (channel_data, thread_handle);
1019                 process_handle=0;
1020                 thread_handle=0;
1021         } else {
1022                 char *cmd=NULL, *dir=NULL, **argv, **env;
1023                 GError *gerr=NULL;
1024                 gboolean ret;
1025                 struct timeval tv;
1026                 
1027                 /* Get usable copies of the cmd, dir and env now
1028                  * rather than in the child process.  This is to
1029                  * prevent the race condition where the parent can
1030                  * return the reply to the client, which then promptly
1031                  * deletes the scratch data before the new process
1032                  * gets to see it.  Also explode argv here so we can
1033                  * use it to set the process name.
1034                  */
1035                 cmd=_wapi_handle_scratch_lookup (process_fork.cmd);
1036                 dir=_wapi_handle_scratch_lookup (process_fork.dir);
1037                 env=_wapi_handle_scratch_lookup_string_array (process_fork.env);
1038
1039                 _wapi_lookup_handle (GUINT_TO_POINTER (process_handle),
1040                                      WAPI_HANDLE_PROCESS,
1041                                      (gpointer *)&process_handle_data,
1042                                      NULL);
1043
1044                 _wapi_lookup_handle (GUINT_TO_POINTER (thread_handle),
1045                                      WAPI_HANDLE_THREAD,
1046                                      (gpointer *)&thread_handle_data,
1047                                      NULL);
1048                 
1049                 ret=g_shell_parse_argv (cmd, NULL, &argv, &gerr);
1050                 if(ret==FALSE) {
1051                         /* FIXME: Could do something with the
1052                          * GError here
1053                          */
1054                         process_handle_data->exec_errno=gerr->code;
1055                 } else {
1056                         LOGDEBUG ("%s: forking", __func__);
1057
1058                         /* Fork, exec cmd with args and optional env,
1059                          * and return the handles with pid and blank
1060                          * thread id
1061                          */
1062                         pid=fork ();
1063                         if(pid==-1) {
1064                                 process_handle_data->exec_errno=errno;
1065                         } else if (pid==0) {
1066                                 /* child */
1067                                 int i;
1068                                 
1069                                 /* should we detach from the process
1070                                  * group? We're already running
1071                                  * without a controlling tty...
1072                                  */
1073
1074                                 /* Connect stdin, stdout and stderr */
1075                                 dup2 (fds[0], 0);
1076                                 dup2 (fds[1], 1);
1077                                 dup2 (fds[2], 2);
1078
1079                                 if(process_fork.inherit!=TRUE) {
1080                                         /* FIXME: do something here */
1081                                 }
1082                                 
1083                                 /* Close all file descriptors */
1084                                 for (i = getdtablesize () - 1; i > 2; i--) {
1085                                         close (i);
1086                                 }
1087                         
1088                                 /* pass process and thread handle info
1089                                  * to the child, so it doesn't have to
1090                                  * do an expensive search over the
1091                                  * whole list
1092                                  */
1093                                 {
1094                                         guint env_count=0;
1095                                         
1096                                         while(env[env_count]!=NULL) {
1097                                                 env_count++;
1098                                         }
1099
1100                                         env=(char **)g_renew (char **, env, env_count+3);
1101                                         
1102                                         env[env_count]=g_strdup_printf ("_WAPI_PROCESS_HANDLE=%d", process_handle);
1103                                         env[env_count+1]=g_strdup_printf ("_WAPI_THREAD_HANDLE=%d", thread_handle);
1104                                         env[env_count+2]=NULL;
1105                                 }
1106
1107 #ifdef DEBUG
1108                                 LOGDEBUG ("%s: exec()ing [%s] in dir [%s]", __func__, cmd, dir);
1109                                 {
1110                                         i=0;
1111                                         while(argv[i]!=NULL) {
1112                                                 LOGDEBUG ("arg %d: [%s]", i, argv[i]);
1113                                                 i++;
1114                                         }
1115
1116                                         i=0;
1117                                         while(env[i]!=NULL) {
1118                                                 LOGDEBUG ("env %d: [%s]", i, env[i]);
1119                                                 i++;
1120                                         }
1121                                 }
1122 #endif
1123                         
1124                                 /* set cwd */
1125                                 if(chdir (dir)==-1) {
1126                                         process_handle_data->exec_errno=errno;
1127                                         exit (-1);
1128                                 }
1129                                 
1130                                 /* exec */
1131                                 execve (argv[0], argv, env);
1132                 
1133                                 /* bummer! */
1134                                 process_handle_data->exec_errno=errno;
1135                                 exit (-1);
1136                         }
1137                 }
1138                 /* parent */
1139
1140                 /* store process name, based on the last section of the cmd */
1141                 {
1142                         char *slash;
1143                         
1144                         /* This should never fail, but it seems it can...
1145                          */
1146                         if (argv[0] != NULL) {
1147                                 slash=strrchr (argv[0], '/');
1148                         
1149                                 if(slash!=NULL) {
1150                                         process_handle_data->proc_name=_wapi_handle_scratch_store (slash+1, strlen (slash+1));
1151                                 } else {
1152                                         process_handle_data->proc_name=_wapi_handle_scratch_store (argv[0], strlen (argv[0]));
1153                                 }
1154                         } else {
1155                                 process_handle_data->proc_name = _wapi_handle_scratch_store (cmd, strlen(cmd));
1156                         }
1157                 }
1158                 
1159                 /* These seem to be the defaults on w2k */
1160                 process_handle_data->min_working_set=204800;
1161                 process_handle_data->max_working_set=1413120;
1162                 
1163                 if(cmd!=NULL) {
1164                         g_free (cmd);
1165                 }
1166                 if(dir!=NULL) {
1167                         g_free (dir);
1168                 }
1169                 g_strfreev (argv);
1170                 g_strfreev (env);
1171                 
1172                 /* store pid */
1173                 process_handle_data->id=pid;
1174                 process_handle_data->main_thread=GUINT_TO_POINTER (thread_handle);
1175                 /* Ignore errors */
1176                 gettimeofday (&tv, NULL);
1177                 _wapi_timeval_to_filetime (&tv,
1178                                            &process_handle_data->create_time);
1179                 
1180                 /* FIXME: if env==0, inherit the env from the current
1181                  * process
1182                  */
1183                 process_handle_data->env=process_fork.env;
1184
1185                 thread_handle_data->process_handle=GUINT_TO_POINTER (process_handle);
1186
1187                 resp.u.process_fork.pid=pid;
1188         }
1189
1190         resp.u.process_fork.process_handle=process_handle;
1191         resp.u.process_fork.thread_handle=thread_handle;
1192
1193         send_reply (channel, &resp);
1194 }
1195
1196 /*
1197  * process_set_share:
1198  * @channel: The client making the request
1199  * @channel_data: The channel data
1200  * @set_share: Set share data passed from the client
1201  *
1202  * Sets file share info
1203  */
1204 static void process_set_share (GIOChannel *channel, ChannelData *channel_data,
1205                                WapiHandleRequest_SetShare set_share)
1206 {
1207         WapiHandleResponse resp = {0};
1208
1209         resp.type = WapiHandleResponseType_SetShare;
1210         
1211         LOGDEBUG ("%s: Setting share for file (dev:0x%llx, ino:%lld) mode 0x%x access 0x%x", __func__, set_share.device, set_share.inode, set_share.sharemode, set_share.access);
1212         
1213         sharemode_set (set_share.device, set_share.inode, set_share.sharemode,
1214                        set_share.access);
1215         
1216         send_reply (channel, &resp);
1217 }
1218
1219 /*
1220  * process_get_or_set_share:
1221  * @channel: The client making the request
1222  * @channel_data: The channel data
1223  * @get_share: GetOrSetShare data passed from the client
1224  *
1225  * Gets a file share status, and sets the status if it doesn't already
1226  * exist
1227  */
1228 static void process_get_or_set_share (GIOChannel *channel,
1229                                       ChannelData *channel_data,
1230                                       WapiHandleRequest_GetOrSetShare get_share)
1231 {
1232         WapiHandleResponse resp = {0};
1233         
1234         resp.type = WapiHandleResponseType_GetOrSetShare;
1235         
1236         LOGDEBUG ("%s: Getting share status for file (dev:0x%llx, ino:%lld)", __func__, get_share.device, get_share.inode);
1237
1238         resp.u.get_or_set_share.exists = sharemode_get (get_share.device, get_share.inode, &resp.u.get_or_set_share.sharemode, &resp.u.get_or_set_share.access);
1239         
1240         if (resp.u.get_or_set_share.exists) {
1241                 LOGDEBUG ("%s: Share mode: 0x%x", __func__, resp.u.get_or_set_share.sharemode);
1242         } else {
1243                 LOGDEBUG ("%s: file share info not already known, setting", __func__);
1244                 sharemode_set (get_share.device, get_share.inode,
1245                                get_share.new_sharemode, get_share.new_access);
1246         }
1247         
1248         send_reply (channel, &resp);
1249 }
1250
1251 /*
1252  * read_message:
1253  * @channel: The client to read the request from
1254  * @open_handles: An array of handles referenced by this client
1255  *
1256  * Read a message (A WapiHandleRequest) from a client and dispatch
1257  * whatever it wants to the process_* calls.  Return TRUE if the message
1258  * was read successfully, FALSE otherwise.
1259  */
1260 static gboolean read_message (GIOChannel *channel, ChannelData *channel_data)
1261 {
1262         WapiHandleRequest req;
1263         int fds[3]={0, 1, 2};
1264         int ret;
1265         gboolean has_fds=FALSE;
1266         
1267         /* Reading data */
1268         ret=_wapi_daemon_request (g_io_channel_unix_get_fd (channel), &req,
1269                                   fds, &has_fds);
1270         if(ret==0) {
1271                 /* Other end went away */
1272                 LOGDEBUG ("Read 0 bytes on fd %d, closing it",
1273                            g_io_channel_unix_get_fd (channel));
1274                 rem_fd (channel, channel_data);
1275                 return(FALSE);
1276         }
1277         
1278         LOGDEBUG ("Process request %d", req.type);
1279         switch(req.type) {
1280         case WapiHandleRequestType_New:
1281                 process_new (channel, channel_data, req.u.new.type);
1282                 break;
1283         case WapiHandleRequestType_Open:
1284 #ifdef DEBUG
1285                 g_assert(req.u.open.handle < _wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT);
1286 #endif
1287                 process_open (channel, channel_data, req.u.open.handle);
1288                 break;
1289         case WapiHandleRequestType_Close:
1290 #ifdef DEBUG
1291                 g_assert(req.u.close.handle < _wapi_shared_data[0]->num_segments * _WAPI_HANDLES_PER_SEGMENT);
1292 #endif
1293                 process_close (channel, channel_data, req.u.close.handle);
1294                 break;
1295         case WapiHandleRequestType_Scratch:
1296                 process_scratch (channel, req.u.scratch.length);
1297                 break;
1298         case WapiHandleRequestType_ScratchFree:
1299                 process_scratch_free (channel, req.u.scratch_free.idx);
1300                 break;
1301         case WapiHandleRequestType_ProcessFork:
1302                 process_process_fork (channel, channel_data,
1303                                       req.u.process_fork, fds);
1304                 break;
1305         case WapiHandleRequestType_ProcessKill:
1306                 process_process_kill (channel, req.u.process_kill);
1307                 break;
1308         case WapiHandleRequestType_SetShare:
1309                 process_set_share (channel, channel_data, req.u.set_share);
1310                 break;
1311         case WapiHandleRequestType_GetOrSetShare:
1312                 process_get_or_set_share (channel, channel_data,
1313                                           req.u.get_or_set_share);
1314                 break;
1315         case WapiHandleRequestType_Error:
1316                 /* fall through */
1317         default:
1318                 /* Catch bogus requests */
1319                 /* FIXME: call rem_fd? */
1320                 break;
1321         }
1322
1323         if(has_fds==TRUE) {
1324                 LOGDEBUG ("%s: closing %d", __func__, fds[0]);
1325                 LOGDEBUG ("%s: closing %d", __func__, fds[1]);
1326                 LOGDEBUG ("%s: closing %d", __func__, fds[2]);
1327                 
1328                 close (fds[0]);
1329                 close (fds[1]);
1330                 close (fds[2]);
1331         }
1332
1333         return(TRUE);
1334 }
1335
1336 /*
1337  * fd_activity:
1338  * @channel: The IO channel that is active
1339  * @condition: The condition that has been satisfied
1340  * @data: A pointer to an array of handles referenced by this client
1341  *
1342  * The callback called by the main loop when there is activity on an
1343  * IO channel.
1344  */
1345 static gboolean fd_activity (GIOChannel *channel, GIOCondition condition,
1346                              gpointer data)
1347 {
1348         int fd=g_io_channel_unix_get_fd (channel);
1349         ChannelData *channel_data=&channels[fd];
1350         GMainContext *context=data;
1351         
1352         if(condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
1353                 LOGDEBUG ("fd %d error", fd);
1354                 rem_fd (channel, channel_data);
1355                 return(FALSE);
1356         }
1357
1358         if(condition & (_IO_PRI)) {
1359                 if(fd==main_sock) {
1360                         int newsock;
1361                         struct sockaddr addr;
1362                         socklen_t addrlen=sizeof(struct sockaddr);
1363                         
1364                         newsock=accept (main_sock, &addr, &addrlen);
1365                         if(newsock==-1) {
1366                                 g_critical ("%s accept error: %s", __func__, g_strerror (errno));
1367                                 cleanup ();
1368                                 exit (-1);
1369                         }
1370
1371                         LOGDEBUG ("accept returning %d", newsock);
1372                         add_fd (newsock, context);
1373                 } else {
1374                         LOGDEBUG ("reading data on fd %d", fd);
1375
1376                         return(read_message (channel, channel_data));
1377                 }
1378                 return(TRUE);
1379         }
1380         
1381         return(FALSE);  /* remove source */
1382 }
1383
1384 /*
1385  * _wapi_daemon_main:
1386  *
1387  * Open socket, create shared mem segment and begin listening for
1388  * clients.
1389  */
1390 void _wapi_daemon_main(gpointer data, gpointer scratch)
1391 {
1392         struct sockaddr_un main_socket_address;
1393         int ret;
1394         GMainContext *context;
1395
1396         LOGDEBUG ("Starting up...");
1397
1398         _wapi_shared_data[0]=data;
1399         _wapi_shared_scratch=scratch;
1400         _wapi_shared_scratch->is_shared=TRUE;
1401         
1402         /* Note that we've got the starting segment already */
1403         _wapi_shared_data[0]->num_segments=1;
1404         _wapi_shm_mapped_segments=1;
1405
1406         _wapi_fd_offset_table_size=getdtablesize ();
1407         _wapi_shared_data[0]->fd_offset_table_size = _wapi_fd_offset_table_size;
1408         
1409         startup ();
1410         
1411         main_sock=socket(PF_UNIX, SOCK_STREAM, 0);
1412
1413         main_socket_address.sun_family=AF_UNIX;
1414         memcpy(main_socket_address.sun_path, _wapi_shared_data[0]->daemon,
1415                MONO_SIZEOF_SUNPATH);
1416
1417         ret=bind(main_sock, (struct sockaddr *)&main_socket_address,
1418                  sizeof(struct sockaddr_un));
1419         if(ret==-1) {
1420                 g_critical ("bind failed: %s", g_strerror (errno));
1421                 _wapi_shared_data[0]->daemon_running=DAEMON_DIED_AT_STARTUP;
1422                 exit(-1);
1423         }
1424
1425         LOGDEBUG("bound");
1426
1427         ret=listen(main_sock, 5);
1428         if(ret==-1) {
1429                 g_critical ("listen failed: %s", g_strerror (errno));
1430                 _wapi_shared_data[0]->daemon_running=DAEMON_DIED_AT_STARTUP;
1431                 exit(-1);
1432         }
1433         LOGDEBUG("listening");
1434
1435         context = g_main_context_new ();
1436
1437         add_fd(main_sock, context);
1438
1439         /* We're finished setting up, let everyone else know we're
1440          * ready.  From now on, it's up to us to delete the shared
1441          * memory segment when appropriate.
1442          */
1443         _wapi_shared_data[0]->daemon_running=DAEMON_RUNNING;
1444
1445         while(TRUE) {
1446                 if(check_processes==TRUE) {
1447                         process_died ();
1448                 }
1449                 
1450                 LOGDEBUG ("polling");
1451
1452                 /* Block until something happens. We don't use
1453                  * g_main_loop_run() because we rely on the SIGCHLD
1454                  * signal interrupting poll() so we can reap child
1455                  * processes as soon as they die, without burning cpu
1456                  * time by polling the flag.
1457                  */
1458                 g_main_context_iteration (context, TRUE);
1459         }
1460 }