/* * look for the node with the given name. if not exist, * create a new one and append to the node list. */ static struct makenode *add_target(const char *name) { struct makenode *__restrict node; struct makenode *prev, *t; node = lookup_target(name); if (node) return node; if (posix_memalign((void*)&node, sizeof(void*), alignof(struct makenode)+strsize(name)) < 0) { fprintf(stderr, "Can't malloc: %s\n", strerror(errno)); exit(1); } memset(node, 0, alignof(struct makenode)+strsize(name)); node->name = ((char*)node)+alignof(struct makenode); strcpy(node->name, name); /* append to the list in alphabetical order */ prev = NULL; for (t = tree_list; t; prev = t, t = t->next) if (strcmp(node->name, t->name) < 0) break; if (prev) prev->next = node; else tree_list = node; node->next = t; tree_entries++; return node; }
/* * mark the selected service as an interactive task * that should run solely */ static void mark_interactive(const char *name) { struct makenode *node = lookup_target(name); if (node) node->interactive = 1; }
static void filter_files(const char *dir, int prefix, int inverse) { char path[64]; int i, ndirs; static struct dirent **dirlist; struct makenode *t, *next; filter_prefix = prefix; #ifdef SUSE /* SuSE */ snprintf(path, sizeof(path), "/etc/init.d/%s.d", dir); #else /* Debian */ snprintf(path, sizeof(path), "/etc/%s.d", dir); #endif #if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600 if ((i = open(path, o_flags|O_DIRECTORY|O_LARGEFILE)) >= 0) { (void)posix_fadvise(i, 0, 0, POSIX_FADV_SEQUENTIAL); (void)posix_fadvise(i, 0, 0, POSIX_FADV_NOREUSE); } #endif ndirs = scandir(path, &dirlist, dirfilter, alphasort); #if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600 if (i >= 0) { (void)posix_fadvise(i, 0, 0, POSIX_FADV_DONTNEED); close(i); } #endif /* mark all matching nodes */ if (ndirs >= 0) { for (i = 0; i < ndirs; i++) { t = lookup_target(dirlist[i]->d_name + 3); if (t) { t->status = 1; t->filter_prefix = filter_prefix; if (asprintf(&t->arg0, "%s/%s", path, dirlist[i]->d_name) < 0) t->arg0 = (char*)0; } free(dirlist[i]); } free(dirlist); } /* deselect non-matching nodes */ for (t = tree_list; t; t = next) { next = t->next; if ((! t->status && ! inverse) || (t->status && inverse)) { /* remove from the list */ struct makelist *x, *nx; struct makenode *p; for (x = t->select; x; x = nx) { nx = x->next; x->node->num_deps--; free(x); } for (x = t->depend; x; x = nx) { nx = x->next; x->node->num_sels--; free(x); } if (t == tree_list) tree_list = next; else { for (p = tree_list; p->next != t; p = p->next) ; p->next = next; } /* don't free the node instance itself - it may be selected * by others */ tree_entries--; continue; } t->status = 0; } }
void h2o_socketpool_connect(h2o_socketpool_connect_request_t **_req, h2o_socketpool_t *pool, h2o_url_t *url, h2o_loop_t *loop, h2o_multithread_receiver_t *getaddr_receiver, h2o_socketpool_connect_cb cb, void *data) { struct pool_entry_t *entry = NULL; struct on_close_data_t *close_data; if (_req != NULL) *_req = NULL; size_t target = SIZE_MAX; h2o_linklist_t *sockets = NULL; /* fetch an entry and return it */ pthread_mutex_lock(&pool->_shared.mutex); destroy_expired(pool); /* TODO lookup outside this critical section */ if (is_global_pool(pool)) { target = lookup_target(pool, url); if (target == SIZE_MAX) { h2o_vector_reserve(NULL, &pool->targets, pool->targets.size + 1); pool->targets.entries[pool->targets.size++] = h2o_socketpool_create_target(url, NULL); target = pool->targets.size - 1; } sockets = &pool->targets.entries[target]->_shared.sockets; } else { sockets = &pool->_shared.sockets; } assert(pool->targets.size != 0); while (!h2o_linklist_is_empty(sockets)) { if (is_global_pool(pool)) { entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, target_link, sockets->next); } else { entry = H2O_STRUCT_FROM_MEMBER(struct pool_entry_t, all_link, sockets->next); } h2o_linklist_unlink(&entry->all_link); h2o_linklist_unlink(&entry->target_link); pthread_mutex_unlock(&pool->_shared.mutex); /* test if the connection is still alive */ char buf[1]; ssize_t rret = recv(entry->sockinfo.fd, buf, 1, MSG_PEEK); if (rret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { /* yes! return it */ size_t entry_target = entry->target; h2o_socket_t *sock = h2o_socket_import(loop, &entry->sockinfo); free(entry); close_data = h2o_mem_alloc(sizeof(*close_data)); close_data->pool = pool; close_data->target = entry_target; sock->on_close.cb = on_close; sock->on_close.data = close_data; cb(sock, NULL, data, &pool->targets.entries[entry_target]->url); return; } /* connection is dead, report, close, and retry */ if (rret <= 0) { static long counter = 0; if (__sync_fetch_and_add(&counter, 1) == 0) fprintf(stderr, "[WARN] detected close by upstream before the expected timeout (see issue #679)\n"); } else { static long counter = 0; if (__sync_fetch_and_add(&counter, 1) == 0) fprintf(stderr, "[WARN] unexpectedly received data to a pooled socket (see issue #679)\n"); } destroy_detached(entry); pthread_mutex_lock(&pool->_shared.mutex); }