| 1123 | } |
| 1124 | |
| 1125 | static int service_loop(struct socketlist *socklist) |
| 1126 | { |
| 1127 | struct sigaction sa; |
| 1128 | struct pollfd *pfd; |
| 1129 | |
| 1130 | CALLOC_ARRAY(pfd, socklist->nr); |
| 1131 | |
| 1132 | for (size_t i = 0; i < socklist->nr; i++) { |
| 1133 | pfd[i].fd = socklist->list[i]; |
| 1134 | pfd[i].events = POLLIN; |
| 1135 | } |
| 1136 | |
| 1137 | sigemptyset(&sa.sa_mask); |
| 1138 | sa.sa_flags = SA_NOCLDSTOP; |
| 1139 | sa.sa_handler = child_handler; |
| 1140 | sigaction(SIGCHLD, &sa, NULL); |
| 1141 | |
| 1142 | for (;;) { |
| 1143 | check_dead_children(); |
| 1144 | |
| 1145 | if (poll(pfd, socklist->nr, -1) < 0) { |
| 1146 | if (errno != EINTR) { |
| 1147 | logerror("Poll failed, resuming: %s", |
| 1148 | strerror(errno)); |
| 1149 | sleep(1); |
| 1150 | } |
| 1151 | continue; |
| 1152 | } |
| 1153 | |
| 1154 | for (size_t i = 0; i < socklist->nr; i++) { |
| 1155 | if (pfd[i].revents & POLLIN) { |
| 1156 | union { |
| 1157 | struct sockaddr sa; |
| 1158 | struct sockaddr_in sai; |
| 1159 | #ifndef NO_IPV6 |
| 1160 | struct sockaddr_in6 sai6; |
| 1161 | #endif |
| 1162 | } ss; |
| 1163 | socklen_t sslen = sizeof(ss); |
| 1164 | int incoming; |
| 1165 | int retry = 3; |
| 1166 | |
| 1167 | redo: |
| 1168 | incoming = accept(pfd[i].fd, &ss.sa, &sslen); |
| 1169 | if (incoming < 0) { |
| 1170 | switch (errno) { |
| 1171 | case EINTR: |
| 1172 | if (--retry) |
| 1173 | goto redo; |
| 1174 | |
| 1175 | /* fallthrough */ |
| 1176 | case EAGAIN: |
| 1177 | case ECONNABORTED: |
| 1178 | continue; |
| 1179 | default: |
| 1180 | die_errno("accept returned"); |
| 1181 | } |
| 1182 | } |