566ff6245f20b6ef80b2bcc9eac29d04ed84d72d
[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 <sys/poll.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <signal.h>
22 #include <sys/wait.h>
23
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
30 #undef DEBUG
31
32 static struct pollfd *pollfds=NULL;
33 static int nfds=0, maxfds=0;
34 /* handle_refs[0] is used by the daemon itself */
35 static gpointer *handle_refs=NULL;
36 static int main_sock;
37
38 /* Set to TRUE by the SIGCHLD signal handler */
39 static volatile gboolean check_processes=FALSE;
40
41 /* Deletes the shared memory segment.  If we're exiting on error,
42  * clients will get EPIPEs.
43  */
44 static void cleanup (void)
45 {
46         _wapi_shm_destroy ();
47 }
48
49 /* If there is only one socket, and no child processes, we can exit.
50  * We test for child processes by counting handle references held by
51  * the daemon.
52  */
53 static void maybe_exit (void)
54 {
55         guint32 *open_handles=handle_refs[0], i;
56
57 #ifdef DEBUG
58         g_message (G_GNUC_PRETTY_FUNCTION ": Seeing if we should exit");
59 #endif
60
61         if(nfds>1) {
62 #ifdef DEBUG
63                 g_message (G_GNUC_PRETTY_FUNCTION ": Still got clients");
64 #endif
65                 return;
66         }
67
68         for(i=0; i<_WAPI_MAX_HANDLES; i++) {
69                 if(open_handles[i]>0) {
70 #ifdef DEBUG
71                         g_message (G_GNUC_PRETTY_FUNCTION
72                                    ": Still got handle references");
73 #endif
74                         return;
75                 }
76         }
77         
78 #ifdef DEBUG
79         g_message (G_GNUC_PRETTY_FUNCTION ": Byebye");
80 #endif
81
82         cleanup ();
83         exit (0);
84 }
85
86 static void signal_handler (int unused)
87 {
88         cleanup ();
89         exit (-1);
90 }
91
92 static void sigchld_handler (int unused)
93 {
94         /* Notice that a child process died */
95         check_processes=TRUE;
96 }
97
98 static void startup (void)
99 {
100         struct sigaction sa;
101         gboolean success;
102         int shm_id;
103         
104         sa.sa_handler=signal_handler;
105         sigemptyset (&sa.sa_mask);
106         sa.sa_flags=0;
107         sigaction (SIGINT, &sa, NULL);
108         sigaction (SIGTERM, &sa, NULL);
109         
110 #ifndef HAVE_MSG_NOSIGNAL
111         sa.sa_handler=SIG_IGN;
112         sigaction (SIGPIPE, &sa, NULL);
113 #endif
114
115         sa.sa_handler=sigchld_handler;
116         sa.sa_flags=SA_NOCLDSTOP;
117         sigaction (SIGCHLD, &sa, NULL);
118         
119         _wapi_shared_data=_wapi_shm_attach (TRUE, &success, &shm_id);
120         if(success==FALSE) {
121                 g_error ("Failed to attach shared memory! (tried shared memory ID 0x%x)", shm_id);
122                 exit (-1);
123         }
124
125         /* Leave the first byte NULL so we create the socket in the
126          * abstrace namespace, not on the filesystem.  (Lets see how
127          * portable _that_ is :)
128          *
129          * The name is intended to be unique, not cryptographically
130          * secure...
131          */
132         snprintf (_wapi_shared_data->daemon+1, 106,
133                   "mono-handle-daemon-%d-%d-%ld", getuid (), getpid (),
134                   time (NULL));
135 }
136
137 static void ref_handle (guint32 idx, guint32 handle)
138 {
139         guint32 *open_handles=handle_refs[idx];
140         
141         if(handle==0) {
142                 return;
143         }
144         
145         _wapi_shared_data->handles[handle].ref++;
146         open_handles[handle]++;
147         
148 #ifdef DEBUG
149         g_message (G_GNUC_PRETTY_FUNCTION
150                    ": handle 0x%x ref now %d (%d this process)", handle,
151                    _wapi_shared_data->handles[handle].ref,
152                    open_handles[handle]);
153 #endif
154 }
155
156 static gboolean unref_handle (guint32 idx, guint32 handle)
157 {
158         guint32 *open_handles=handle_refs[idx];
159         gboolean destroy=FALSE;
160         
161         if(handle==0) {
162                 return(FALSE);
163         }
164         
165         _wapi_shared_data->handles[handle].ref--;
166         open_handles[handle]--;
167         
168 #ifdef DEBUG
169         g_message (G_GNUC_PRETTY_FUNCTION
170                    ": handle 0x%x ref now %d (%d this process)", handle,
171                    _wapi_shared_data->handles[handle].ref,
172                    open_handles[handle]);
173 #endif
174
175         if(open_handles[handle]==0) {
176                 /* This client has released the handle */
177                 destroy=TRUE;
178         }
179         
180         if(_wapi_shared_data->handles[handle].ref==0) {
181                 if (open_handles[handle]!=0) {
182                         g_warning (G_GNUC_PRETTY_FUNCTION ": per-process open_handles mismatch, set to %d, should be 0", open_handles[handle]);
183                 }
184                 
185 #ifdef DEBUG
186                 g_message (G_GNUC_PRETTY_FUNCTION ": Destroying handle 0x%x",
187                            handle);
188 #endif
189                 
190                 _wapi_handle_ops_close_shared (GUINT_TO_POINTER (handle));
191                 
192                 _wapi_shared_data->handles[handle].type=WAPI_HANDLE_UNUSED;
193                 mono_mutex_destroy (&_wapi_shared_data->handles[handle].signal_mutex);
194                 pthread_cond_destroy (&_wapi_shared_data->handles[handle].signal_cond);
195                 memset (&_wapi_shared_data->handles[handle].u, '\0', sizeof(_wapi_shared_data->handles[handle].u));
196         }
197
198         if(idx==0) {
199                 /* The daemon released a reference, so see if it's
200                  * ready to exit
201                  */
202                 maybe_exit ();
203         }
204         
205         return(destroy);
206 }
207
208 static void add_fd(int fd)
209 {
210         if(nfds==maxfds) {
211                 /* extend the array */
212                 maxfds+=10;
213                 pollfds=g_renew (struct pollfd, pollfds, maxfds);
214                 handle_refs=g_renew (gpointer, handle_refs, maxfds);
215         }
216
217         pollfds[nfds].fd=fd;
218         pollfds[nfds].events=POLLIN;
219         pollfds[nfds].revents=0;
220         
221         handle_refs[nfds]=g_new0 (guint32, _WAPI_MAX_HANDLES);
222
223         nfds++;
224 }
225
226 static void rem_fd(int idx)
227 {
228         guint32 *open_handles=handle_refs[idx], handle_count;
229         int i, j;
230         
231         if(idx==0) {
232                 /* We shouldn't be deleting the daemon's fd */
233                 g_warning (G_GNUC_PRETTY_FUNCTION ": Deleting daemon fd!");
234                 cleanup ();
235                 exit (-1);
236         }
237         
238 #ifdef DEBUG
239         g_message (G_GNUC_PRETTY_FUNCTION ": Removing client at %d", idx);
240 #endif
241
242         close(pollfds[idx].fd);
243
244         for(i=0; i<_WAPI_MAX_HANDLES; i++) {
245                 handle_count=open_handles[i];
246                 
247                 for(j=0; j<handle_count; j++) {
248 #ifdef DEBUG
249                         g_message (G_GNUC_PRETTY_FUNCTION ": closing handle 0x%x for client at index %d", i, idx);
250 #endif
251                         /* Ignore the hint to the client to destroy
252                          * the handle private data
253                          */
254                         unref_handle (idx, i);
255                 }
256         }
257         
258         nfds--;
259         if(nfds==1) {
260                 /* Just the master socket left, so see if we can
261                  * cleanup and exit
262                  */
263                 maybe_exit ();
264         }
265         
266         memset(&pollfds[idx], '\0', sizeof(struct pollfd));
267         g_free (handle_refs[idx]);
268         
269         if(idx<nfds) {
270                 memmove(&pollfds[idx], &pollfds[idx+1],
271                         sizeof(struct pollfd) * (nfds-idx));
272                 memmove (&handle_refs[idx], &handle_refs[idx+1],
273                          sizeof(guint32) * (nfds-idx));
274         }
275 }
276
277 static gboolean process_compare (gpointer handle, gpointer user_data)
278 {
279         struct _WapiHandle_process *process_handle;
280         gboolean ok;
281         pid_t pid;
282         
283         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
284                                 (gpointer *)&process_handle, NULL);
285         if(ok==FALSE) {
286                 g_warning (G_GNUC_PRETTY_FUNCTION
287                            ": error looking up process handle %p", handle);
288                 return(FALSE);
289         }
290
291         pid=GPOINTER_TO_UINT (user_data);
292         if(process_handle->id==pid) {
293                 return(TRUE);
294         } else {
295                 return(FALSE);
296         }
297 }
298
299 static gboolean process_thread_compare (gpointer handle, gpointer user_data)
300 {
301         struct _WapiHandle_thread *thread_handle;
302         gboolean ok;
303         
304         ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
305                                 (gpointer *)&thread_handle, NULL);
306         if(ok==FALSE) {
307                 g_warning (G_GNUC_PRETTY_FUNCTION
308                            ": error looking up thread handle %p", handle);
309                 return(FALSE);
310         }
311
312         if(thread_handle->process_handle==user_data) {
313                 /* Signal the handle.  Don't use
314                  * _wapi_handle_set_signal_state() unless we have
315                  * process-shared pthread support.
316                  */
317 #ifdef DEBUG
318                 g_message (G_GNUC_PRETTY_FUNCTION ": Set thread handle %p signalled, because its process died", handle);
319 #endif
320
321                 thread_handle->exitstatus=0;
322
323 #ifdef _POSIX_THREAD_PROCESS_SHARED
324                 _wapi_handle_lock_handle (handle);
325                 _wapi_handle_set_signal_state (handle, TRUE, TRUE);
326                 _wapi_handle_unlock_handle (handle);
327 #else
328                 /* Just tweak the signal state directly.  This is not
329                  * recommended behaviour, but it works for threads
330                  * because they can never become unsignalled.  There
331                  * are some nasty kludges in the handle waiting code
332                  * to cope with missing condition signals for when
333                  * process-shared pthread support is missing.
334                  */
335                 _wapi_shared_data->handles[GPOINTER_TO_UINT (handle)].signalled=TRUE;
336 #endif /* _POSIX_THREAD_PROCESS_SHARED */
337         }
338         
339         /* Return false to keep searching */
340         return(FALSE);
341 }
342
343 /* Find the handle associated with pid, mark it dead and record exit
344  * status.  Finds all thread handles associated with this process
345  * handle, and marks those signalled too, with exitstatus '0'.  It
346  * also drops the daemon's reference to the handle, and the thread
347  * pointed at by main_thread.
348  */
349 static void process_post_mortem (pid_t pid, int status)
350 {
351         gpointer process_handle;
352         struct _WapiHandle_process *process_handle_data;
353         
354         process_handle=_wapi_search_handle (WAPI_HANDLE_PROCESS,
355                                             process_compare,
356                                             GUINT_TO_POINTER (pid),
357                                             (gpointer *)&process_handle_data,
358                                             NULL);
359         if(process_handle==0) {
360                 g_warning (G_GNUC_PRETTY_FUNCTION
361                            ": Couldn't find handle for process %d!", pid);
362         } else {
363                 /* Signal the handle.  Don't use
364                  * _wapi_handle_set_signal_state() unless we have
365                  * process-shared pthread support.
366                  */
367 #ifdef DEBUG
368                 g_message (G_GNUC_PRETTY_FUNCTION
369                            ": Set process %d exitstatus to %d", pid,
370                            WEXITSTATUS (status));
371 #endif
372                 
373                 /* Technically WEXITSTATUS is only valid if the
374                  * process exited normally, but I don't care if the
375                  * process caught a signal or not.
376                  */
377                 process_handle_data->exitstatus=WEXITSTATUS (status);
378                 _wapi_time_t_to_filetime (time (NULL),
379                                           &process_handle_data->exit_time);
380
381 #ifdef _POSIX_THREAD_PROCESS_SHARED
382                 _wapi_handle_lock_handle (process_handle);
383                 _wapi_handle_set_signal_state (process_handle, TRUE, TRUE);
384                 _wapi_handle_unlock_handle (process_handle);
385 #else
386                 /* Just tweak the signal state directly.  This is not
387                  * recommended behaviour, but it works for processes
388                  * because they can never become unsignalled.  There
389                  * are some nasty kludges in the handle waiting code
390                  * to cope with missing condition signals for when
391                  * process-shared pthread support is missing.
392                  */
393                 _wapi_shared_data->handles[GPOINTER_TO_UINT (process_handle)].signalled=TRUE;
394 #endif /* _POSIX_THREAD_PROCESS_SHARED */
395         }
396
397         /* Find all threads that have their process
398          * handle==process_handle.  Ignore the return value, all the
399          * work will be done in the compare func
400          */
401         (void)_wapi_search_handle (WAPI_HANDLE_THREAD, process_thread_compare,
402                                    process_handle, NULL, NULL);
403
404         unref_handle (0, GPOINTER_TO_UINT (process_handle_data->main_thread));
405         unref_handle (0, GPOINTER_TO_UINT (process_handle));
406 }
407
408 static void process_died (void)
409 {
410         int status;
411         pid_t pid;
412         
413         check_processes=FALSE;
414
415 #ifdef DEBUG
416         g_message (G_GNUC_PRETTY_FUNCTION ": Reaping processes");
417 #endif
418
419         while(TRUE) {
420                 pid=waitpid (-1, &status, WNOHANG);
421                 if(pid==0 || pid==-1) {
422                         /* Finished waiting.  I was checking pid==-1
423                          * separately but was getting ECHILD when
424                          * there were no more child processes (which
425                          * doesnt seem to conform to the man page)
426                          */
427                         return;
428                 } else {
429                         /* pid contains the ID of a dead process */
430 #ifdef DEBUG
431                         g_message (G_GNUC_PRETTY_FUNCTION ": process %d reaped", pid);
432 #endif
433                         process_post_mortem (pid, status);
434                 }
435         }
436 }
437
438 static void send_reply (guint32 idx, WapiHandleResponse *resp)
439 {
440         /* send message */
441         _wapi_daemon_response (pollfds[idx].fd, resp);
442 }
443
444 static void process_new (guint32 idx, WapiHandleType type)
445 {
446         guint32 handle;
447         WapiHandleResponse resp;
448         
449         /* handle might be set to 0.  This is handled at the client end */
450         handle=_wapi_handle_new_internal (type);
451         ref_handle (idx, handle);
452
453 #ifdef DEBUG
454         g_message (G_GNUC_PRETTY_FUNCTION ": returning new handle 0x%x",
455                    handle);
456 #endif
457
458         resp.type=WapiHandleResponseType_New;
459         resp.u.new.type=type;
460         resp.u.new.handle=handle;
461                         
462         send_reply (idx, &resp);
463 }
464
465 static void process_open (guint32 idx, guint32 handle)
466 {
467         WapiHandleResponse resp;
468         struct _WapiHandleShared *shared=&_wapi_shared_data->handles[handle];
469                 
470         if(shared->type!=WAPI_HANDLE_UNUSED && handle!=0) {
471                 ref_handle (idx, handle);
472
473 #ifdef DEBUG
474                 g_message (G_GNUC_PRETTY_FUNCTION
475                            ": returning new handle 0x%x", handle);
476 #endif
477
478                 resp.type=WapiHandleResponseType_Open;
479                 resp.u.new.type=shared->type;
480                 resp.u.new.handle=handle;
481                         
482                 send_reply (idx, &resp);
483
484                 return;
485         }
486
487         resp.type=WapiHandleResponseType_Open;
488         resp.u.new.handle=0;
489                         
490         send_reply (idx, &resp);
491 }
492
493 static void process_close (guint32 idx, guint32 handle)
494 {
495         WapiHandleResponse resp;
496         
497         resp.type=WapiHandleResponseType_Close;
498         resp.u.close.destroy=unref_handle (idx, handle);
499
500 #ifdef DEBUG
501         g_message (G_GNUC_PRETTY_FUNCTION ": unreffing handle 0x%x", handle);
502 #endif
503                         
504         send_reply (idx, &resp);
505 }
506
507 static void process_scratch (guint32 idx, guint32 length)
508 {
509         WapiHandleResponse resp;
510         
511         resp.type=WapiHandleResponseType_Scratch;
512         resp.u.scratch.idx=_wapi_handle_scratch_store_internal (length);
513
514 #ifdef DEBUG
515         g_message (G_GNUC_PRETTY_FUNCTION ": allocating scratch index 0x%x",
516                    resp.u.scratch.idx);
517 #endif
518                         
519         send_reply (idx, &resp);
520 }
521
522 static void process_scratch_free (guint32 idx, guint32 scratch_idx)
523 {
524         WapiHandleResponse resp;
525         
526         resp.type=WapiHandleResponseType_ScratchFree;
527         _wapi_handle_scratch_delete_internal (scratch_idx);
528
529 #ifdef DEBUG
530         g_message (G_GNUC_PRETTY_FUNCTION ": deleting scratch index 0x%x",
531                    scratch_idx);
532 #endif
533                         
534         send_reply (idx, &resp);
535 }
536
537 static void process_process_fork (guint32 idx,
538                                   WapiHandleRequest_ProcessFork process_fork)
539 {
540         WapiHandleResponse resp;
541         guint32 process_handle, thread_handle;
542         struct _WapiHandle_process *process_handle_data;
543         struct _WapiHandle_thread *thread_handle_data;
544         pid_t pid;
545         
546         resp.type=WapiHandleResponseType_ProcessFork;
547         
548         /* Create handles first, so the child process can store exec
549          * errors.  Either handle might be set to 0, if this happens
550          * just reply to the client without bothering to fork.  The
551          * client must check if either handle is 0 and take
552          * appropriate error handling action.
553          */
554         process_handle=_wapi_handle_new_internal (WAPI_HANDLE_PROCESS);
555         ref_handle (0, process_handle);
556         ref_handle (idx, process_handle);
557         
558         thread_handle=_wapi_handle_new_internal (WAPI_HANDLE_THREAD);
559         ref_handle (0, thread_handle);
560         ref_handle (idx, thread_handle);
561         
562         if(process_handle==0 || thread_handle==0) {
563                 /* unref_handle() copes with the handle being 0 */
564                 unref_handle (0, process_handle);
565                 unref_handle (idx, process_handle);
566                 unref_handle (0, thread_handle);
567                 unref_handle (idx, thread_handle);
568                 process_handle=0;
569                 thread_handle=0;
570         } else {
571                 char *cmd=NULL, *args=NULL;
572                         
573                 /* Get usable copies of the cmd and args now rather
574                  * than in the child process.  This is to prevent the
575                  * race condition where the parent can return the
576                  * reply to the client, which then promptly deletes
577                  * the scratch data before the new process gets to see
578                  * it.
579                  */
580                 cmd=_wapi_handle_scratch_lookup_as_string (process_fork.cmd);
581                 if(process_fork.args!=0) {
582                         args=_wapi_handle_scratch_lookup_as_string (process_fork.args);
583                 }
584
585 #ifdef DEBUG
586                 g_message (G_GNUC_PRETTY_FUNCTION ": forking");
587 #endif
588
589                 _wapi_lookup_handle (GUINT_TO_POINTER (process_handle),
590                                      WAPI_HANDLE_PROCESS,
591                                      (gpointer *)&process_handle_data, NULL);
592
593                 _wapi_lookup_handle (GUINT_TO_POINTER (thread_handle),
594                                      WAPI_HANDLE_THREAD,
595                                      (gpointer *)&thread_handle_data, NULL);
596
597                 /* Fork, exec cmd with args and optional env, and
598                  * return the handles with pid and blank thread id
599                  */
600                 pid=fork ();
601                 if(pid==-1) {
602                         process_handle_data->exec_errno=errno;
603                 } else if (pid==0) {
604                         /* child */
605                         char **argv;
606                         
607                         /* should we detach from the process group? 
608                          * We're already running without a controlling
609                          * tty...
610                          */
611                         if(process_fork.inherit!=TRUE) {
612                                 /* Close all file descriptors */
613                         }
614
615                         /* Connect stdin, stdout and stderr */
616                         
617 #ifdef DEBUG
618                         g_message (G_GNUC_PRETTY_FUNCTION
619                                    ": exec()ing [%s] args [%s]", cmd, args);
620 #endif          
621                 
622                         if(args!=NULL) {
623                                 argv=g_strsplit (args, " \t", 0);
624                         } else {
625                                 argv=g_new0 (char *, 1);
626                         }
627                         
628                         /* exec */
629                         execv (cmd, argv);
630                 
631                         /* bummer! */
632                         process_handle_data->exec_errno=errno;
633                         exit (-1);
634                 }
635                 /* parent */
636                 
637                 /* store pid */
638                 process_handle_data->id=pid;
639                 process_handle_data->main_thread=GUINT_TO_POINTER (thread_handle);
640                 _wapi_time_t_to_filetime (time (NULL),
641                                           &process_handle_data->create_time);
642                 
643                 /* FIXME: if env==0, inherit the env from the current
644                  * process
645                  */
646                 process_handle_data->env=process_fork.env;
647
648                 thread_handle_data->process_handle=GUINT_TO_POINTER (process_handle);
649
650                 resp.u.process_fork.pid=pid;
651         }
652                         
653         resp.u.process_fork.process_handle=process_handle;
654         resp.u.process_fork.thread_handle=thread_handle;
655
656         send_reply (idx, &resp);
657 }
658
659 static void read_message (guint32 idx)
660 {
661         WapiHandleRequest req;
662         
663         /* Reading data */
664         _wapi_daemon_request (pollfds[idx].fd, &req);
665         switch(req.type) {
666         case WapiHandleRequestType_New:
667                 process_new (idx, req.u.new.type);
668                 break;
669         case WapiHandleRequestType_Open:
670                 process_open (idx, req.u.open.handle);
671                 break;
672         case WapiHandleRequestType_Close:
673                 process_close (idx, req.u.close.handle);
674                 break;
675         case WapiHandleRequestType_Scratch:
676                 process_scratch (idx, req.u.scratch.length);
677                 break;
678         case WapiHandleRequestType_ScratchFree:
679                 process_scratch_free (idx, req.u.scratch_free.idx);
680                 break;
681         case WapiHandleRequestType_ProcessFork:
682                 process_process_fork (idx, req.u.process_fork);
683                 break;
684         }
685 }
686
687 int main(int argc, char **argv)
688 {
689         struct sockaddr_un main_socket_address;
690         int ret;
691
692 #ifdef DEBUG
693         g_message ("Starting up...");
694 #endif
695
696         startup ();
697         
698         main_sock=socket(PF_UNIX, SOCK_STREAM, 0);
699
700         main_socket_address.sun_family=AF_UNIX;
701         memcpy(main_socket_address.sun_path, _wapi_shared_data->daemon, 108);
702
703         ret=bind(main_sock, (struct sockaddr *)&main_socket_address,
704                  sizeof(struct sockaddr_un));
705         if(ret==-1) {
706                 g_warning ("bind failed: %s", strerror (errno));
707                 _wapi_shared_data->daemon_running=2;
708                 exit(-1);
709         }
710
711 #ifdef DEBUG
712         g_message("bound");
713 #endif
714
715         ret=listen(main_sock, 5);
716         if(ret==-1) {
717                 g_warning ("listen failed: %s", strerror (errno));
718                 _wapi_shared_data->daemon_running=2;
719                 exit(-1);
720         }
721
722 #ifdef DEBUG
723         g_message("listening");
724 #endif
725
726         add_fd(main_sock);
727
728         /* We're finished setting up, let everyone else know we're
729          * ready.  From now on, it's up to us to delete the shared
730          * memory segment when appropriate.
731          */
732         _wapi_shared_data->daemon_running=1;
733
734         while(TRUE) {
735                 int i;
736
737                 if(check_processes==TRUE) {
738                         process_died ();
739                 }
740                 
741 #ifdef DEBUG
742                 g_message ("polling");
743 #endif
744
745                 /* Block until something happens */
746                 ret=poll(pollfds, nfds, -1);
747                 if(ret==-1 && errno!=EINTR) {
748                         g_message ("poll error: %s", strerror (errno));
749                         cleanup ();
750                         exit(-1);
751                 }
752
753                 for(i=0; i<nfds; i++) {
754                         if(((pollfds[i].revents&POLLHUP)==POLLHUP) ||
755                            ((pollfds[i].revents&POLLERR)==POLLERR) ||
756                            ((pollfds[i].revents&POLLNVAL)==POLLNVAL)) {
757 #ifdef DEBUG
758                                 g_message ("fd[%d] %d error", i,
759                                            pollfds[i].fd);
760 #endif
761                                 rem_fd(i);
762                         } else if((pollfds[i].revents&POLLIN)==POLLIN) {
763                                 if(pollfds[i].fd==main_sock) {
764                                         int newsock;
765                                         struct sockaddr addr;
766                                         socklen_t addrlen=sizeof(struct sockaddr);
767                                         newsock=accept(main_sock, &addr,
768                                                        &addrlen);
769                                         if(newsock==-1) {
770                                                 g_message("accept error: %s",
771                                                           strerror (errno));
772                                                 cleanup ();
773                                                 exit(-1);
774                                         }
775 #ifdef DEBUG
776                                         g_message ("accept returning %d",
777                                                    newsock);
778 #endif
779                                         add_fd(newsock);
780                                 } else {
781 #ifdef DEBUG
782                                         g_message ("reading data on fd %d",
783                                                    pollfds[i].fd);
784 #endif
785                                         read_message (i);
786                                 }
787                         }
788                 }
789         }
790 }