Tizen 2.1 base
[sdk/target/sdbd.git] / src / fdevent.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sys/ioctl.h>
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <errno.h>
24
25 #include <fcntl.h>
26
27 #include <stdarg.h>
28 #include <stddef.h>
29
30 #include "fdevent.h"
31 #include "transport.h"
32 #include "sysdeps.h"
33
34
35 /* !!! Do not enable DEBUG for the sdb that will run as the server:
36 ** both stdout and stderr are used to communicate between the client
37 ** and server. Any extra output will cause failures.
38 */
39 #define DEBUG 0   /* non-0 will break sdb server */
40
41 // This socket is used when a subproc shell service exists.
42 // It wakes up the fdevent_loop() and cause the correct handling
43 // of the shell's pseudo-tty master. I.e. force close it.
44 int SHELL_EXIT_NOTIFY_FD = -1;
45
46 static void fatal(const char *fn, const char *fmt, ...)
47 {
48     va_list ap;
49     va_start(ap, fmt);
50     fprintf(stderr, "%s:", fn);
51     vfprintf(stderr, fmt, ap);
52     va_end(ap);
53     abort();
54 }
55
56 #define FATAL(x...) fatal(__FUNCTION__, x)
57
58 #if DEBUG
59 #define D(...) \
60     do { \
61         sdb_mutex_lock(&D_lock);               \
62         int save_errno = errno;                \
63         fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__);  \
64         errno = save_errno;                    \
65         fprintf(stderr, __VA_ARGS__);          \
66         sdb_mutex_unlock(&D_lock);             \
67         errno = save_errno;                    \
68     } while(0)
69 static void dump_fde(fdevent *fde, const char *info)
70 {
71     sdb_mutex_lock(&D_lock);
72     fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
73             fde->state & FDE_READ ? 'R' : ' ',
74             fde->state & FDE_WRITE ? 'W' : ' ',
75             fde->state & FDE_ERROR ? 'E' : ' ',
76             info);
77     sdb_mutex_unlock(&D_lock);
78 }
79 #else
80 #define D(...) ((void)0)
81 #define dump_fde(fde, info) do { } while(0)
82 #endif
83
84 #define FDE_EVENTMASK  0x00ff
85 #define FDE_STATEMASK  0xff00
86
87 #define FDE_ACTIVE     0x0100
88 #define FDE_PENDING    0x0200
89 #define FDE_CREATED    0x0400
90
91 static void fdevent_plist_enqueue(fdevent *node);
92 static void fdevent_plist_remove(fdevent *node);
93 static fdevent *fdevent_plist_dequeue(void);
94 static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
95
96 static fdevent list_pending = {
97     .next = &list_pending,
98     .prev = &list_pending,
99 };
100
101 static fdevent **fd_table = 0;
102 static int fd_table_max = 0;
103
104 #ifdef CRAPTASTIC
105 //HAVE_EPOLL
106
107 #include <sys/epoll.h>
108
109 static int epoll_fd = -1;
110
111 static void fdevent_init()
112 {
113         /* XXX: what's a good size for the passed in hint? */
114     epoll_fd = epoll_create(256);
115
116     if(epoll_fd < 0) {
117         perror("epoll_create() failed");
118         exit(1);
119     }
120
121         /* mark for close-on-exec */
122     fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
123 }
124
125 static void fdevent_connect(fdevent *fde)
126 {
127     struct epoll_event ev;
128
129     memset(&ev, 0, sizeof(ev));
130     ev.events = 0;
131     ev.data.ptr = fde;
132
133 #if 0
134     if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
135         perror("epoll_ctl() failed\n");
136         exit(1);
137     }
138 #endif
139 }
140
141 static void fdevent_disconnect(fdevent *fde)
142 {
143     struct epoll_event ev;
144
145     memset(&ev, 0, sizeof(ev));
146     ev.events = 0;
147     ev.data.ptr = fde;
148
149         /* technically we only need to delete if we
150         ** were actively monitoring events, but let's
151         ** be aggressive and do it anyway, just in case
152         ** something's out of sync
153         */
154     epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
155 }
156
157 static void fdevent_update(fdevent *fde, unsigned events)
158 {
159     struct epoll_event ev;
160     int active;
161
162     active = (fde->state & FDE_EVENTMASK) != 0;
163
164     memset(&ev, 0, sizeof(ev));
165     ev.events = 0;
166     ev.data.ptr = fde;
167
168     if(events & FDE_READ) ev.events |= EPOLLIN;
169     if(events & FDE_WRITE) ev.events |= EPOLLOUT;
170     if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
171
172     fde->state = (fde->state & FDE_STATEMASK) | events;
173
174     if(active) {
175             /* we're already active. if we're changing to *no*
176             ** events being monitored, we need to delete, otherwise
177             ** we need to just modify
178             */
179         if(ev.events) {
180             if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
181                 perror("epoll_ctl() failed\n");
182                 exit(1);
183             }
184         } else {
185             if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
186                 perror("epoll_ctl() failed\n");
187                 exit(1);
188             }
189         }
190     } else {
191             /* we're not active.  if we're watching events, we need
192             ** to add, otherwise we can just do nothing
193             */
194         if(ev.events) {
195             if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
196                 perror("epoll_ctl() failed\n");
197                 exit(1);
198             }
199         }
200     }
201 }
202
203 static void fdevent_process()
204 {
205     struct epoll_event events[256];
206     fdevent *fde;
207     int i, n;
208
209     n = epoll_wait(epoll_fd, events, 256, -1);
210
211     if(n < 0) {
212         if(errno == EINTR) return;
213         perror("epoll_wait");
214         exit(1);
215     }
216
217     for(i = 0; i < n; i++) {
218         struct epoll_event *ev = events + i;
219         fde = ev->data.ptr;
220
221         if(ev->events & EPOLLIN) {
222             fde->events |= FDE_READ;
223         }
224         if(ev->events & EPOLLOUT) {
225             fde->events |= FDE_WRITE;
226         }
227         if(ev->events & (EPOLLERR | EPOLLHUP)) {
228             fde->events |= FDE_ERROR;
229         }
230         if(fde->events) {
231             if(fde->state & FDE_PENDING) continue;
232             fde->state |= FDE_PENDING;
233             fdevent_plist_enqueue(fde);
234         }
235     }
236 }
237
238 #else /* USE_SELECT */
239
240 #ifdef HAVE_WINSOCK
241 #include <winsock2.h>
242 #else
243 #include <sys/select.h>
244 #endif
245
246 static fd_set read_fds;
247 static fd_set write_fds;
248 static fd_set error_fds;
249
250 static int select_n = 0;
251
252 static void fdevent_init(void)
253 {
254     FD_ZERO(&read_fds);
255     FD_ZERO(&write_fds);
256     FD_ZERO(&error_fds);
257 }
258
259 static void fdevent_connect(fdevent *fde)
260 {
261     if(fde->fd >= select_n) {
262         select_n = fde->fd + 1;
263     }
264 }
265
266 static void fdevent_disconnect(fdevent *fde)
267 {
268     int i, n;
269
270     FD_CLR(fde->fd, &read_fds);
271     FD_CLR(fde->fd, &write_fds);
272     FD_CLR(fde->fd, &error_fds);
273
274     for(n = 0, i = 0; i < select_n; i++) {
275         if(fd_table[i] != 0) n = i;
276     }
277     select_n = n + 1;
278 }
279
280 static void fdevent_update(fdevent *fde, unsigned events)
281 {
282     if(events & FDE_READ) {
283         FD_SET(fde->fd, &read_fds);
284     } else {
285         FD_CLR(fde->fd, &read_fds);
286     }
287     if(events & FDE_WRITE) {
288         FD_SET(fde->fd, &write_fds);
289     } else {
290         FD_CLR(fde->fd, &write_fds);
291     }
292     if(events & FDE_ERROR) {
293         FD_SET(fde->fd, &error_fds);
294     } else {
295         FD_CLR(fde->fd, &error_fds);
296     }
297
298     fde->state = (fde->state & FDE_STATEMASK) | events;
299 }
300
301 /* Looks at fd_table[] for bad FDs and sets bit in fds.
302 ** Returns the number of bad FDs.
303 */
304 static int fdevent_fd_check(fd_set *fds)
305 {
306     int i, n = 0;
307     fdevent *fde;
308
309     for(i = 0; i < select_n; i++) {
310         fde = fd_table[i];
311         if(fde == 0) continue;
312         if(fcntl(i, F_GETFL, NULL) < 0) {
313             FD_SET(i, fds);
314             n++;
315             // fde->state |= FDE_DONT_CLOSE;
316
317         }
318     }
319     return n;
320 }
321
322 #if !DEBUG
323 static inline void dump_all_fds(const char *extra_msg) {}
324 #else
325 static void dump_all_fds(const char *extra_msg)
326 {
327 int i;
328     fdevent *fde;
329     // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
330     char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
331     size_t max_chars = FD_SETSIZE * 6 + 1;
332     int printed_out;
333 #define SAFE_SPRINTF(...)                                                    \
334     do {                                                                     \
335         printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
336         if (printed_out <= 0) {                                              \
337             D("... snprintf failed.\n");                                     \
338             return;                                                          \
339         }                                                                    \
340         if (max_chars < (unsigned int)printed_out) {                         \
341             D("... snprintf out of space.\n");                               \
342             return;                                                          \
343         }                                                                    \
344         pb += printed_out;                                                   \
345         max_chars -= printed_out;                                            \
346     } while(0)
347
348     for(i = 0; i < select_n; i++) {
349         fde = fd_table[i];
350         SAFE_SPRINTF("%d", i);
351         if(fde == 0) {
352             SAFE_SPRINTF("? ");
353             continue;
354         }
355         if(fcntl(i, F_GETFL, NULL) < 0) {
356             SAFE_SPRINTF("b");
357         }
358         SAFE_SPRINTF(" ");
359     }
360     D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
361 }
362 #endif
363
364 static int fdevent_process()
365 {
366     int i, n;
367     fdevent *fde;
368     unsigned events;
369     fd_set rfd, wfd, efd;
370
371     memcpy(&rfd, &read_fds, sizeof(fd_set));
372     memcpy(&wfd, &write_fds, sizeof(fd_set));
373     memcpy(&efd, &error_fds, sizeof(fd_set));
374
375     dump_all_fds("pre select()");
376
377     n = select(select_n, &rfd, &wfd, &efd, NULL);
378     int saved_errno = errno;
379     D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
380
381     dump_all_fds("post select()");
382
383     if(n < 0) {
384         switch(saved_errno) {
385         case EINTR: return -1;
386         case EBADF:
387             // Can't trust the FD sets after an error.
388             FD_ZERO(&wfd);
389             FD_ZERO(&efd);
390             FD_ZERO(&rfd);
391             break;
392         default:
393             D("Unexpected select() error=%d\n", saved_errno);
394             return 0;
395         }
396     }
397     if(n <= 0) {
398         // We fake a read, as the rest of the code assumes
399         // that errors will be detected at that point.
400         n = fdevent_fd_check(&rfd);
401     }
402
403     for(i = 0; (i < select_n) && (n > 0); i++) {
404         events = 0;
405         if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
406         if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
407         if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
408
409         if(events) {
410             fde = fd_table[i];
411             if(fde == 0)
412               FATAL("missing fde for fd %d\n", i);
413
414             fde->events |= events;
415
416             D("got events fde->fd=%d events=%04x, state=%04x\n",
417                 fde->fd, fde->events, fde->state);
418             if(fde->state & FDE_PENDING) continue;
419             fde->state |= FDE_PENDING;
420             fdevent_plist_enqueue(fde);
421         }
422     }
423
424     return 0;
425 }
426
427 #endif
428
429 static void fdevent_register(fdevent *fde)
430 {
431     if(fde->fd < 0) {
432         FATAL("bogus negative fd (%d)\n", fde->fd);
433     }
434
435     if(fde->fd >= fd_table_max) {
436         int oldmax = fd_table_max;
437         if(fde->fd > 32000) {
438             FATAL("bogus huuuuge fd (%d)\n", fde->fd);
439         }
440         if(fd_table_max == 0) {
441             fdevent_init();
442             fd_table_max = 256;
443         }
444         while(fd_table_max <= fde->fd) {
445             fd_table_max *= 2;
446         }
447         fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
448         if(fd_table == 0) {
449             FATAL("could not expand fd_table to %d entries\n", fd_table_max);
450         }
451         memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
452     }
453
454     fd_table[fde->fd] = fde;
455 }
456
457 static void fdevent_unregister(fdevent *fde)
458 {
459     if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
460         FATAL("fd out of range (%d)\n", fde->fd);
461     }
462
463     if(fd_table[fde->fd] != fde) {
464         FATAL("fd_table out of sync [%d]\n", fde->fd);
465     }
466
467     fd_table[fde->fd] = 0;
468
469     if(!(fde->state & FDE_DONT_CLOSE)) {
470         dump_fde(fde, "close");
471         sdb_close(fde->fd);
472     }
473 }
474
475 static void fdevent_plist_enqueue(fdevent *node)
476 {
477     fdevent *list = &list_pending;
478
479     node->next = list;
480     node->prev = list->prev;
481     node->prev->next = node;
482     list->prev = node;
483 }
484
485 static void fdevent_plist_remove(fdevent *node)
486 {
487     node->prev->next = node->next;
488     node->next->prev = node->prev;
489     node->next = 0;
490     node->prev = 0;
491 }
492
493 static fdevent *fdevent_plist_dequeue(void)
494 {
495     fdevent *list = &list_pending;
496     fdevent *node = list->next;
497
498     if(node == list) return 0;
499
500     list->next = node->next;
501     list->next->prev = list;
502     node->next = 0;
503     node->prev = 0;
504
505     return node;
506 }
507
508 static void fdevent_call_fdfunc(fdevent* fde)
509 {
510     unsigned events = fde->events;
511     fde->events = 0;
512     if(!(fde->state & FDE_PENDING)) return;
513     fde->state &= (~FDE_PENDING);
514     dump_fde(fde, "callback");
515     fde->func(fde->fd, events, fde->arg);
516 }
517
518 static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
519 {
520
521     D("subproc handling on fd=%d ev=%04x\n", fd, ev);
522
523     // Hook oneself back into the fde's suitable for select() on read.
524     if((fd < 0) || (fd >= fd_table_max)) {
525         FATAL("fd %d out of range for fd_table \n", fd);
526     }
527     fdevent *fde = fd_table[fd];
528     fdevent_add(fde, FDE_READ);
529
530     if(ev & FDE_READ){
531       int subproc_fd;
532
533       if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
534           FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
535       }
536       if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
537           D("subproc_fd %d out of range 0, fd_table_max=%d\n",
538             subproc_fd, fd_table_max);
539           return;
540       }
541       fdevent *subproc_fde = fd_table[subproc_fd];
542       if(!subproc_fde) {
543           D("subproc_fd %d cleared from fd_table\n", subproc_fd);
544           return;
545       }
546       if(subproc_fde->fd != subproc_fd) {
547           // Already reallocated?
548           D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
549           return;
550       }
551
552       subproc_fde->force_eof = 1;
553
554       int rcount = 0;
555       ioctl(subproc_fd, FIONREAD, &rcount);
556       D("subproc with fd=%d  has rcount=%d err=%d\n",
557         subproc_fd, rcount, errno);
558
559       if(rcount) {
560         // If there is data left, it will show up in the select().
561         // This works because there is no other thread reading that
562         // data when in this fd_func().
563         return;
564       }
565
566       D("subproc_fde.state=%04x\n", subproc_fde->state);
567       subproc_fde->events |= FDE_READ;
568       if(subproc_fde->state & FDE_PENDING) {
569         return;
570       }
571       subproc_fde->state |= FDE_PENDING;
572       fdevent_call_fdfunc(subproc_fde);
573     }
574 }
575
576 fdevent *fdevent_create(int fd, fd_func func, void *arg)
577 {
578     fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
579     if(fde == 0) return 0;
580     fdevent_install(fde, fd, func, arg);
581     fde->state |= FDE_CREATED;
582     return fde;
583 }
584
585 void fdevent_destroy(fdevent *fde)
586 {
587     if(fde == 0) return;
588     if(!(fde->state & FDE_CREATED)) {
589         FATAL("fde %p not created by fdevent_create()\n", fde);
590     }
591     fdevent_remove(fde);
592 }
593
594 void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
595 {
596     memset(fde, 0, sizeof(fdevent));
597     fde->state = FDE_ACTIVE;
598     fde->fd = fd;
599     fde->force_eof = 0;
600     fde->func = func;
601     fde->arg = arg;
602
603 #ifndef HAVE_WINSOCK
604     if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
605         D("failed to close fd exec:%d\n",fd);
606     }
607 #endif
608     fdevent_register(fde);
609     dump_fde(fde, "connect");
610     fdevent_connect(fde);
611     fde->state |= FDE_ACTIVE;
612 }
613
614 void fdevent_remove(fdevent *fde)
615 {
616     if(fde->state & FDE_PENDING) {
617         fdevent_plist_remove(fde);
618     }
619
620     if(fde->state & FDE_ACTIVE) {
621         fdevent_disconnect(fde);
622         dump_fde(fde, "disconnect");
623         fdevent_unregister(fde);
624     }
625
626     fde->state = 0;
627     fde->events = 0;
628 }
629
630
631 void fdevent_set(fdevent *fde, unsigned events)
632 {
633     events &= FDE_EVENTMASK;
634
635     if((fde->state & FDE_EVENTMASK) == events) return;
636
637     if(fde->state & FDE_ACTIVE) {
638         fdevent_update(fde, events);
639         dump_fde(fde, "update");
640     }
641
642     fde->state = (fde->state & FDE_STATEMASK) | events;
643
644     if(fde->state & FDE_PENDING) {
645             /* if we're pending, make sure
646             ** we don't signal an event that
647             ** is no longer wanted.
648             */
649         fde->events &= (~events);
650         if(fde->events == 0) {
651             fdevent_plist_remove(fde);
652             fde->state &= (~FDE_PENDING);
653         }
654     }
655 }
656
657 void fdevent_add(fdevent *fde, unsigned events)
658 {
659     fdevent_set(
660         fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
661 }
662
663 void fdevent_del(fdevent *fde, unsigned events)
664 {
665     fdevent_set(
666         fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
667 }
668
669 void fdevent_subproc_setup()
670 {
671     int s[2];
672
673     if(sdb_socketpair(s)) {
674         FATAL("cannot create shell-exit socket-pair\n");
675     }
676     SHELL_EXIT_NOTIFY_FD = s[0];
677     fdevent *fde;
678     fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
679     if(!fde)
680       FATAL("cannot create fdevent for shell-exit handler\n");
681     fdevent_add(fde, FDE_READ);
682 }
683
684 void fdevent_loop()
685 {
686     fdevent *fde;
687     fdevent_subproc_setup();
688
689     for(;;) {
690         D("--- ---- waiting for events\n");
691
692         if (fdevent_process() < 0) {
693             return;
694         }
695
696         while((fde = fdevent_plist_dequeue())) {
697             fdevent_call_fdfunc(fde);
698         }
699     }
700 }