// mainloop thread static void forward_message(int type, bool padding, struct socket_message * result) { struct server_socket_message *sm; int sz = sizeof(*sm); if (padding) { if (result->data) { sz += strlen(result->data); } else { result->data = ""; } } sm = (struct server_socket_message *)server_malloc(sz); sm->type = type; sm->id = result->id; sm->ud = result->ud; if (padding) { sm->buffer = NULL; strcpy((char*)(sm+1), result->data); } else { sm->buffer = result->data; } struct server_message message; message.source = 0; message.session = 0; message.data = sm; message.sz = sz | PTYPE_SOCKET << HANDLE_REMOTE_SHIFT;//高8位作为消息类型 if (server_context_push((uint32_t)result->opaque, &message)) { // todo: report somewhere to close socket // don't call server_socket_close here (It will block mainloop) server_free(sm->buffer); server_free(sm); } }
int server_unregister(struct btd_adapter *adapter, uint16_t id) { struct network_adapter *na; struct network_server *ns; na = find_adapter(adapters, adapter); if (!na) return -EINVAL; ns = find_server(na->servers, id); if (!ns) return -EINVAL; na->servers = g_slist_remove(na->servers, ns); server_free(ns); if (g_slist_length(na->servers) > 0) return 0; g_dbus_unregister_interface(btd_get_dbus_connection(), adapter_get_path(adapter), NETWORK_SERVER_INTERFACE); return 0; }
static DBusMessage *add_sap_service_record(DBusConnection *conn, DBusMessage *msg, void *data) { DBG(""); sdp_record_t *record = NULL; GError *gerr = NULL; record = create_sap_record(SAP_SERVER_CHANNEL); if (!record) { error("Creating SAP SDP record failed."); goto sdp_err; } if (add_record_to_server(&server->src, record) < 0) { error("Adding SAP SDP record to the SDP server failed."); sdp_record_free(record); goto sdp_err; } server->record_id = record->handle; DBG("EXIT"); return dbus_message_new_method_return(msg); sdp_err: server_free(server); sap_exit(); return dbus_message_new_method_return(msg); }
//收回handle int server_handle_retire(uint32_t handle) { int ret = 0; struct handle_storage *s = H; rwlock_wlock(&s->lock); uint32_t hash = handle & (s->slot_size-1); struct server_context * ctx = s->slot[hash]; if (ctx != NULL && server_context_handle(ctx) == handle) { s->slot[hash] = NULL;//置空,哈希表腾出空间 ret = 1; int i; int j=0, n=s->name_count; for (i=0; i<n; ++i) { if (s->name[i].handle == handle) {//在 name 表中 找到 handle 对应的 name free掉 server_free(s->name[i].name); continue; } else if (i!=j) {//说明free了一个name s->name[j] = s->name[i];//因此需要将后续元素移到前面 } ++j; } s->name_count = j; } rwlock_wunlock(&s->lock); if (ctx) { server_context_release(ctx);//free server_ctx } return ret; }
static void _insert_name_before(struct handle_storage *s, char *name, uint32_t handle, int before) { if (s->name_count >= s->name_cap) { s->name_cap *= 2; assert(s->name_cap <= MAX_SLOT_SIZE); struct handle_name * n = server_malloc(s->name_cap * sizeof(struct handle_name)); int i; for (i=0;i<before;i++) { n[i] = s->name[i]; } for (i=before;i<s->name_count;i++) { n[i+1] = s->name[i]; } server_free(s->name); s->name = n; } else { int i; for (i=s->name_count;i>before;i--) { s->name[i] = s->name[i-1]; } } s->name[before].name = name; s->name[before].handle = handle; s->name_count ++; }
static void hwf_container_dispose(GObject *object) { HwfContainer *container; container = HWF_CONTAINER(object); while (container->servers != NULL) { Server *server = container->servers->data; container->servers = g_slist_remove(container->servers, container->servers->data); server_free(server); } if (container->runner) { g_object_unref(container->runner); container->runner = NULL; } if (container->runtime) { g_object_unref(container->runtime); container->runtime = NULL; } G_OBJECT_CLASS(hwf_container_parent_class)->dispose(object); }
static int speedtest(int dl_enable, int ul_enable) { int i; client_config_t client; server_config_t servers[CLOSEST_SERVERS_NUM]; server_config_t best_server; for (i = 0; i < CLOSEST_SERVERS_NUM; i++) { init_server(&servers[i]); } init_server(&best_server); init_client(&client); if (get_speedtest_config(&client)) { fprintf(stderr, "get_speedtest_config error!\n"); nvram_set("speedtest_running", "2"); return -1; } if (get_nearest_servers(&client, servers)) { fprintf(stderr, "get_nearest_servers error!\n"); nvram_set("speedtest_running", "2"); return -1; } client_free(&client); if (get_lowest_latency_server(servers, &best_server)) { fprintf(stderr, "get_lowest_latency_server error!\n"); nvram_set("speedtest_running", "2"); return -1; } if (dl_enable == 1) { if (test_download_speed(&best_server)) { fprintf(stderr, "test_download_speed error!\n"); nvram_set("speedtest_running", "2"); return -1; } } if (ul_enable == 1) { finished = (double)0; if (test_upload_speed(&best_server)) { fprintf(stderr, "test_upload_speed error!\n"); nvram_set("speedtest_running", "2"); return -1; } } for (i = 0; i < CLOSEST_SERVERS_NUM; i++) { server_free(&servers[i]); } nvram_set("speedtest_running", "1"); nvram_commit(); return 0; }
static void destroy_sap_interface(void *data) { struct sap_server *server = data; DBG("Unregistered interface %s on path %s", SAP_SERVER_INTERFACE, server->path); server_free(server); }
//先打包成C,再打包成string static int lpackstring(lua_State *L) { _luaseri_pack(L); char * str = (char *)lua_touserdata(L, -2); int sz = lua_tointeger(L, -1); lua_pushlstring(L, str, sz); server_free(str); return 1; }
/** * Clean up the srv instance. */ void TearDown( ) { if( srv != NULL ) { server_free( srv ); } log_free( ); status_counter_free( ); }
/** * test1 Allocate a server and do lots of other things * */ static int test1() { SERVER *server; int result; char *status; /* Server tests */ ss_dfprintf(stderr, "testserver : creating server called MyServer"); server = server_alloc("MyServer", "HTTPD", 9876); skygw_log_sync_all(); //ss_info_dassert(NULL != service, "New server with valid protocol and port must not be null"); //ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation"); ss_dfprintf(stderr, "\t..done\nTest Parameter for Server."); ss_info_dassert(NULL == serverGetParameter(server, "name"), "Parameter should be null when not set"); serverAddParameter(server, "name", "value"); skygw_log_sync_all(); ss_info_dassert(0 == strcmp("value", serverGetParameter(server, "name")), "Parameter should be returned correctly"); ss_dfprintf(stderr, "\t..done\nTesting Unique Name for Server."); ss_info_dassert(NULL == server_find_by_unique_name("uniquename"), "Should not find non-existent unique name."); server_set_unique_name(server, "uniquename"); skygw_log_sync_all(); ss_info_dassert(server == server_find_by_unique_name("uniquename"), "Should find by unique name."); ss_dfprintf(stderr, "\t..done\nTesting Status Setting for Server."); status = server_status(server); skygw_log_sync_all(); ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running by default."); if (NULL != status) free(status); server_set_status(server, SERVER_MASTER); status = server_status(server); skygw_log_sync_all(); ss_info_dassert(0 == strcmp("Master, Running", status), "Should find correct status."); server_clear_status(server, SERVER_MASTER); free(status); status = server_status(server); skygw_log_sync_all(); ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running after master status cleared."); if (NULL != status) free(status); ss_dfprintf(stderr, "\t..done\nRun Prints for Server and all Servers."); printServer(server); printAllServers(); skygw_log_sync_all(); ss_dfprintf(stderr, "\t..done\nFreeing Server."); ss_info_dassert(0 != server_free(server), "Free should succeed"); ss_dfprintf(stderr, "\t..done\n"); return 0; }
static void wb_free(struct write_block *wb) { struct block *blk = wb->head; blk = blk->next; // the first block is on stack while (blk) { struct block * next = blk->next; server_free(blk); blk = next; } wb->head = NULL; wb->current = NULL; wb->ptr = 0; wb->len = 0; }
int server_socket_send(struct server_context *ctx, int id, void *buffer, int sz) { int64_t wsz = socket_server_send(SOCKET_SERVER, id, buffer, sz); if (wsz < 0) { server_free(buffer); return -1; } else if (wsz > 1024 * 1024) { int kb4 = wsz / 1024 / 4; if (kb4 % 256 == 0) { server_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id); } } return 0; }
int server_register(struct btd_adapter *adapter, uint16_t id) { struct network_adapter *na; struct network_server *ns; const char *path; na = find_adapter(adapters, adapter); if (!na) { na = create_adapter(adapter); if (!na) return -EINVAL; adapters = g_slist_append(adapters, na); } ns = find_server(na->servers, id); if (ns) return 0; ns = g_new0(struct network_server, 1); ns->name = g_strdup("Network service"); path = adapter_get_path(adapter); if (g_slist_length(na->servers) > 0) goto done; if (!g_dbus_register_interface(btd_get_dbus_connection(), path, NETWORK_SERVER_INTERFACE, server_methods, NULL, NULL, na, path_unregister)) { error("D-Bus failed to register %s interface", NETWORK_SERVER_INTERFACE); server_free(ns); return -1; } DBG("Registered interface %s on path %s", NETWORK_SERVER_INTERFACE, path); done: bacpy(&ns->src, btd_adapter_get_address(adapter)); ns->id = id; ns->na = na; ns->record_id = 0; na->servers = g_slist_append(na->servers, ns); return 0; }
void nfs41_server_deref( IN nfs41_server *server) { EnterCriticalSection(&g_server_list.lock); server->ref_count--; dprintf(SRVLVL, "nfs41_server_deref(%s) count %d\n", server->owner, server->ref_count); if (server->ref_count == 0) { list_remove(&server->entry); server_free(server); } LeaveCriticalSection(&g_server_list.lock); }
void server_remove(char *name) { dbase_server *server = servers; if (name) { server = server_find_name(name, servers); } if (server) { if (server == servers) servers = NULL; server_free(server, 1); } }
extern EXPORT_API gboolean gst_dvb_css_wc_start(const gchar *address, gint port, gboolean followup, guint32 max_freq_error_ppm, gboolean isDebug) { GST_DEBUG("dvb_css_wc_start\n"); G_LOCK(mutex); sServer = server_new(); if (sServer == NULL) { goto server_struct_not_initialized; } gst_init(NULL, NULL); sServer->loop = g_main_loop_new(NULL, FALSE); sServer->clock = gst_system_clock_obtain(); if(isDebug == FALSE){ sServer->gstdvbcsswcserver = gst_dvb_css_wc_server_new(sServer->clock, address, port, followup, max_freq_error_ppm); } else{ sServer->gstdvbcsswcserver = gst_net_time_provider_new(sServer->clock, address, port); } if (sServer->gstdvbcsswcserver == NULL) { GST_ERROR("Dvb_css_wc server not created\n"); goto cleanup; } g_object_get(sServer->gstdvbcsswcserver, "port", &port, NULL); GST_DEBUG("Published network clock on port %u\n", port); sServer->thread = g_thread_try_new("dvb_css_wc_thread", (GThreadFunc) g_main_loop_run, sServer->loop, NULL); if (sServer->thread == NULL) { GST_ERROR("Thread for dvb_css_wc server not created\n"); goto cleanup; } GST_DEBUG("Dvb_css_wc server started\n"); G_UNLOCK(mutex); return TRUE; /* ERRORS */ server_struct_not_initialized:{ GST_ERROR("Dvb_css_wc server struct not initialized\n"); G_UNLOCK(mutex); return FALSE; } cleanup:{ server_free(&sServer); G_UNLOCK(mutex); return FALSE; } }
static void path_unregister(void *data) { struct network_server *ns = data; struct network_adapter *na = ns->na; DBG("Unregistered interface %s on path %s", ns->iface, adapter_get_path(na->adapter)); na->servers = g_slist_remove(na->servers, ns); server_free(ns); if (na->servers) return; adapters = g_slist_remove(adapters, na); adapter_free(na); }
// cleanup 'server' static void cleanup_servers(system_data_t *sysdata) { server_t *server; assert(sysdata); assert(sysdata->servers); while ((server = ll_pop_head(sysdata->servers))) { server_free(server); free(server); } assert(ll_count(sysdata->servers) == 0); sysdata->servers = ll_free(sysdata->servers); assert(sysdata->servers == NULL); sysdata->servers = NULL; }
extern EXPORT_API void gst_dvb_css_wc_stop(void) { GST_DEBUG("dvb_css_wc_stop\n"); G_LOCK(mutex); if (sServer == NULL) { G_UNLOCK(mutex); return; } GST_DEBUG("Stopping dvb_css_wc server\n"); if (sServer->loop != NULL) { g_main_loop_quit(sServer->loop); g_thread_join(sServer->thread); sServer->thread = NULL; sServer->loop = NULL; } server_free(&sServer); GST_INFO("Dvb_css_wc server stopped\n"); G_UNLOCK(mutex); }
int server_register(struct btd_adapter *adapter) { struct network_adapter *na; struct network_server *ns; const char *path; na = find_adapter(adapters, adapter); if (!na) { na = create_adapter(adapter); if (!na) return -EINVAL; adapters = g_slist_append(adapters, na); } ns = find_server(na->servers, BNEP_SVC_NAP); if (ns) return 0; ns = g_new0(struct network_server, 1); ns->iface = g_strdup(NETWORK_SERVER_INTERFACE); ns->name = g_strdup("Network service"); path = adapter_get_path(adapter); if (!g_dbus_register_interface(connection, path, ns->iface, server_methods, NULL, NULL, ns, path_unregister)) { error("D-Bus failed to register %s interface", ns->iface); server_free(ns); return -1; } adapter_get_address(adapter, &ns->src); ns->id = BNEP_SVC_NAP; ns->na = na; ns->record_id = 0; na->servers = g_slist_append(na->servers, ns); DBG("Registered interface %s on path %s", ns->iface, path); return 0; }
//释放资源 static int ltrash(lua_State *L) { int t = lua_type(L,1); switch (t) { case LUA_TSTRING: { break; } case LUA_TLIGHTUSERDATA: { void * msg = lua_touserdata(L,1); luaL_checkinteger(L,2); server_free(msg); break; } default: luaL_error(L, "server.trash invalid param %s", lua_typename(L,t)); } return 0; }
//解析数据 static int harbor_unpack(lua_State *L) { struct remote_message *rmsg = lua_touserdata(L,1); if (rmsg->destination.handle == 0) { lua_pushlstring(L, rmsg->destination.name, strlen(rmsg->destination.name)); } else { lua_pushinteger(L, rmsg->destination.handle); } int type = rmsg->sz >> HANDLE_REMOTE_SHIFT;//消息类型 rmsg->sz &= HANDLE_MASK;//消息大小 if (rmsg->message != NULL) { lua_pushinteger(L, type); lua_pushlstring(L, (char *)rmsg->message, rmsg->sz); lua_pushinteger(L, rmsg->sz); server_free((void *)rmsg->message); } return 4;//返回参数数量 }
void server_start(server *s) { int i; s->base = event_base_new(); s->signal = event_new(s->base, SIGINT, EV_SIGNAL|EV_PERSIST, &server_sig_handler, s); event_add(s->signal, NULL); s->fd = server_setup_socket(s->cfg->ip, s->cfg->port); assert(s->fd != -1); /* start workers */ for(i=0; i<s->cfg->workers; i++) { worker_start(s->w[i]); } event_base_dispatch(s->base); server_free(s); exit(EXIT_SUCCESS); }
int main(int argc, char* argv[]) { signal(SIGINT, sig_handler); unsigned short port = 21; if(argc == 2) { port = (unsigned short) atoi(argv[1]); } struct Command ftp_command; // initialize command struct command_init(&ftp_command); // import commands... feat_command_import(&ftp_command); base_command_import(&ftp_command); ext_command_import(&ftp_command); command_register_connect(&ftp_command, client_connect); command_register_disconnect(&ftp_command, client_disconnect); // initialize server struct server_init(&ftp_server, &ftp_command, port); std::cout << "Started server!" << std::endl; uint32_t ret = server_run(&ftp_server); std::cout << "Server stopped (code: " << ret << ")!" << std::endl; server_free(&ftp_server); command_free(&ftp_command); return 0; }
void server_free(dbase_server *server, int top) { int i; if (!server) return; for (i = 0; i < server->children_count; i++) server_free(server->children[i], 0); i = 0; while (i < nicks_count) { if ((server->numeric[0] == nicks_num[i]->numeric[0]) && (server->numeric[1] == nicks_num[i]->numeric[1])) { if (nicks_remove(nicks_num[i]->numeric) < 0) i++; } else i++; } if (top) { if (server->parent) { for (i = 0; i < server->parent->children_count; i++) { if (server->parent->children[i] == server) { server->parent->children[i] = server->parent->children[--server->parent->children_count]; server->parent->children = (dbase_server **) realloc(server->parent->children, sizeof(dbase_server *)*server->parent->children_count); break; } } } } xfree(server->children); xfree(server->desc); xfree(server->name); xfree(server); }
//注册ctx,将ctx存到handle_storage哈希表中,并得到一个handle uint32_t server_handle_register(struct server_context *ctx) { struct handle_storage *s = H; rwlock_wlock(&s->lock); for (;;) { int i; for (i=0;i<s->slot_size;i++) { uint32_t handle = (i+s->handle_index) & HANDLE_MASK;//高8位清0,保留低24位 int hash = handle & (s->slot_size-1);//保证handle不能大于slot_size,使得hash取值在[0, slot_size-1] if (s->slot[hash] == NULL) {//找到未使用的slot,将这个 ctx 放入这个 slot 中 s->slot[hash] = ctx; s->handle_index = handle + 1;//移动handle_index,方便下次使用 rwlock_wunlock(&s->lock); handle |= s->harbor;//高8位用于存放分布式id return handle; } } assert((s->slot_size*2 - 1) <= HANDLE_MASK);//确保 扩大2倍空间后 总共handle即 slot的数量不超过 24位的限制 //哈希表扩大2倍 struct server_context ** new_slot = server_malloc(s->slot_size * 2 * sizeof(struct server_context *)); memset(new_slot, 0, s->slot_size * 2 * sizeof(struct server_context *)); //将原来的数据拷贝到新的空间 for (i=0;i<s->slot_size;i++) { int hash = server_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);//映射新的 hash 值 assert(new_slot[hash] == NULL); new_slot[hash] = s->slot[i]; } server_free(s->slot); s->slot = new_slot; s->slot_size *= 2; } }
void session_free (session *killsess) { server *killserv = killsess->server; session *sess; GSList *list; int oldidx; plugin_emit_dummy_print (killsess, "Close Context"); if (current_tab == killsess) current_tab = NULL; if (killserv->server_session == killsess) killserv->server_session = NULL; if (killserv->front_session == killsess) { /* front_session is closed, find a valid replacement */ killserv->front_session = NULL; list = sess_list; while (list) { sess = (session *) list->data; if (sess != killsess && sess->server == killserv) { killserv->front_session = sess; if (!killserv->server_session) killserv->server_session = sess; break; } list = list->next; } } if (!killserv->server_session) killserv->server_session = killserv->front_session; sess_list = g_slist_remove (sess_list, killsess); if (killsess->type == SESS_CHANNEL) userlist_free (killsess); oldidx = killsess->lastact_idx; if (oldidx != LACT_NONE) sess_list_by_lastact[oldidx] = g_list_remove(sess_list_by_lastact[oldidx], killsess); exec_notify_kill (killsess); log_close (killsess); scrollback_close (killsess); chanopt_save (killsess); send_quit_or_part (killsess); history_free (&killsess->history); if (killsess->topic) free (killsess->topic); if (killsess->current_modes) free (killsess->current_modes); fe_session_callback (killsess); if (current_sess == killsess) { current_sess = NULL; if (sess_list) current_sess = sess_list->data; } free (killsess); if (!sess_list && !in_hexchat_exit) hexchat_exit (); /* sess_list is empty, quit! */ list = sess_list; while (list) { sess = (session *) list->data; if (sess->server == killserv) return; /* this server is still being used! */ list = list->next; } server_free (killserv); }
int main (int argc, char **argv) { server *srv = NULL; int print_config = 0; int test_config = 0; int i_am_root; int o; int num_childs = 0; int pid_fd = -1, fd; size_t i; #ifdef HAVE_SIGACTION struct sigaction act; #endif #ifdef HAVE_GETRLIMIT struct rlimit rlim; #endif #ifdef USE_ALARM struct itimerval interval; interval.it_interval.tv_sec = 1; interval.it_interval.tv_usec = 0; interval.it_value.tv_sec = 1; interval.it_value.tv_usec = 0; #endif /* for nice %b handling in strfime() */ setlocale(LC_TIME, "C"); if (NULL == (srv = server_init())) { fprintf(stderr, "did this really happen?\n"); return -1; } /* init structs done */ srv->srvconf.port = 0; #ifdef HAVE_GETUID i_am_root = (getuid() == 0); #else i_am_root = 0; #endif srv->srvconf.dont_daemonize = 0; while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { switch(o) { case 'f': if (srv->config_storage) { log_error_write(srv, __FILE__, __LINE__, "s", "Can only read one config file. Use the include command to use multiple config files."); server_free(srv); return -1; } if (config_read(srv, optarg)) { server_free(srv); return -1; } break; case 'm': buffer_copy_string(srv->srvconf.modules_dir, optarg); break; case 'p': print_config = 1; break; case 't': test_config = 1; break; case 'D': srv->srvconf.dont_daemonize = 1; break; case 'v': show_version(); return 0; case 'V': show_features(); return 0; case 'h': show_help(); return 0; default: show_help(); server_free(srv); return -1; } } if (!srv->config_storage) { log_error_write(srv, __FILE__, __LINE__, "s", "No configuration available. Try using -f option."); server_free(srv); return -1; } if (print_config) { data_unset *dc = srv->config_context->data[0]; if (dc) { dc->print(dc, 0); fprintf(stdout, "\n"); } else { /* shouldn't happend */ fprintf(stderr, "global config not found\n"); } } if (test_config) { printf("Syntax OK\n"); } if (test_config || print_config) { server_free(srv); return 0; } /* close stdin and stdout, as they are not needed */ openDevNull(STDIN_FILENO); openDevNull(STDOUT_FILENO); if (0 != config_set_defaults(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "setting default values failed"); server_free(srv); return -1; } /* UID handling */ #ifdef HAVE_GETUID if (!i_am_root && issetugid()) { /* we are setuid-root */ log_error_write(srv, __FILE__, __LINE__, "s", "Are you nuts ? Don't apply a SUID bit to this binary"); server_free(srv); return -1; } #endif /* check document-root */ if (srv->config_storage[0]->document_root->used <= 1) { log_error_write(srv, __FILE__, __LINE__, "s", "document-root is not set\n"); server_free(srv); return -1; } if (plugins_load(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "loading plugins finally failed"); plugins_free(srv); server_free(srv); return -1; } /* open pid file BEFORE chroot */ if (srv->srvconf.pid_file->used) { if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { struct stat st; if (errno != EEXIST) { log_error_write(srv, __FILE__, __LINE__, "sbs", "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); return -1; } if (0 != stat(srv->srvconf.pid_file->ptr, &st)) { log_error_write(srv, __FILE__, __LINE__, "sbs", "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno)); } if (!S_ISREG(st.st_mode)) { log_error_write(srv, __FILE__, __LINE__, "sb", "pid-file exists and isn't regular file:", srv->srvconf.pid_file); return -1; } if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { log_error_write(srv, __FILE__, __LINE__, "sbs", "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); return -1; } } } if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* select limits itself * * as it is a hard limit and will lead to a segfault we add some safety * */ srv->max_fds = FD_SETSIZE - 200; } else { srv->max_fds = 4096; } if (i_am_root) { struct group *grp = NULL; struct passwd *pwd = NULL; int use_rlimit = 1; #ifdef HAVE_VALGRIND_VALGRIND_H if (RUNNING_ON_VALGRIND) use_rlimit = 0; #endif #ifdef HAVE_GETRLIMIT if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, "ss", "couldn't get 'max filedescriptors'", strerror(errno)); return -1; } if (use_rlimit && srv->srvconf.max_fds) { /* set rlimits */ rlim.rlim_cur = srv->srvconf.max_fds; rlim.rlim_max = srv->srvconf.max_fds; if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, "ss", "couldn't set 'max filedescriptors'", strerror(errno)); return -1; } } if (srv->event_handler == FDEVENT_HANDLER_SELECT) { srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200; } else { srv->max_fds = rlim.rlim_cur; } /* set core file rlimit, if enable_cores is set */ if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) { rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_CORE, &rlim); } #endif if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ if (srv->max_fds > ((int)FD_SETSIZE) - 200) { log_error_write(srv, __FILE__, __LINE__, "sd", "can't raise max filedescriptors above", FD_SETSIZE - 200, "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds."); return -1; } } #ifdef HAVE_PWD_H /* set user and group */ if (srv->srvconf.username->used) { if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) { log_error_write(srv, __FILE__, __LINE__, "sb", "can't find username", srv->srvconf.username); return -1; } if (pwd->pw_uid == 0) { log_error_write(srv, __FILE__, __LINE__, "s", "I will not set uid to 0\n"); return -1; } } if (srv->srvconf.groupname->used) { if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) { log_error_write(srv, __FILE__, __LINE__, "sb", "can't find groupname", srv->srvconf.groupname); return -1; } if (grp->gr_gid == 0) { log_error_write(srv, __FILE__, __LINE__, "s", "I will not set gid to 0\n"); return -1; } } #endif /* we need root-perms for port < 1024 */ if (0 != network_init(srv)) { plugins_free(srv); server_free(srv); return -1; } #ifdef HAVE_PWD_H /* * Change group before chroot, when we have access * to /etc/group * */ if (NULL != grp) { setgid(grp->gr_gid); setgroups(0, NULL); if (srv->srvconf.username->used) { initgroups(srv->srvconf.username->ptr, grp->gr_gid); } } #endif #ifdef HAVE_CHROOT if (srv->srvconf.changeroot->used) { tzset(); if (-1 == chroot(srv->srvconf.changeroot->ptr)) { log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno)); return -1; } if (-1 == chdir("/")) { log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno)); return -1; } } #endif #ifdef HAVE_PWD_H /* drop root privs */ if (NULL != pwd) { setuid(pwd->pw_uid); } #endif #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE) /** * on IRIX 6.5.30 they have prctl() but no DUMPABLE */ if (srv->srvconf.enable_cores) { prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } #endif } else { #ifdef HAVE_GETRLIMIT if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, "ss", "couldn't get 'max filedescriptors'", strerror(errno)); return -1; } /** * we are not root can can't increase the fd-limit, but we can reduce it */ if (srv->srvconf.max_fds && srv->srvconf.max_fds < rlim.rlim_cur) { /* set rlimits */ rlim.rlim_cur = srv->srvconf.max_fds; if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, "ss", "couldn't set 'max filedescriptors'", strerror(errno)); return -1; } } if (srv->event_handler == FDEVENT_HANDLER_SELECT) { srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200; } else { srv->max_fds = rlim.rlim_cur; } /* set core file rlimit, if enable_cores is set */ if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) { rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_CORE, &rlim); } #endif if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ if (srv->max_fds > ((int)FD_SETSIZE) - 200) { log_error_write(srv, __FILE__, __LINE__, "sd", "can't raise max filedescriptors above", FD_SETSIZE - 200, "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds."); return -1; } } if (0 != network_init(srv)) { plugins_free(srv); server_free(srv); return -1; } } /* set max-conns */ if (srv->srvconf.max_conns > srv->max_fds/2) { /* we can't have more connections than max-fds/2 */ log_error_write(srv, __FILE__, __LINE__, "sdd", "can't have more connections than fds/2: ", srv->srvconf.max_conns, srv->max_fds); srv->max_conns = srv->max_fds/2; } else if (srv->srvconf.max_conns) { /* otherwise respect the wishes of the user */ srv->max_conns = srv->srvconf.max_conns; } else { /* or use the default: we really don't want to hit max-fds */ srv->max_conns = srv->max_fds/3; } if (HANDLER_GO_ON != plugins_call_init(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down."); plugins_free(srv); network_close(srv); server_free(srv); return -1; } #ifdef HAVE_FORK /* network is up, let's deamonize ourself */ if (srv->srvconf.dont_daemonize == 0) daemonize(); #endif srv->gid = getgid(); srv->uid = getuid(); /* write pid file */ if (pid_fd != -1) { buffer_copy_long(srv->tmp_buf, getpid()); buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n")); write(pid_fd, srv->tmp_buf->ptr, srv->tmp_buf->used - 1); close(pid_fd); pid_fd = -1; } /* Close stderr ASAP in the child process to make sure that nothing * is being written to that fd which may not be valid anymore. */ if (-1 == log_error_open(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down."); plugins_free(srv); network_close(srv); server_free(srv); return -1; } if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down."); plugins_free(srv); network_close(srv); server_free(srv); return -1; } /* dump unused config-keys */ for (i = 0; i < srv->config_context->used; i++) { array *config = ((data_config *)srv->config_context->data[i])->value; size_t j; for (j = 0; config && j < config->used; j++) { data_unset *du = config->data[j]; /* all var.* is known as user defined variable */ if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) { continue; } if (NULL == array_get_element(srv->config_touched, du->key->ptr)) { log_error_write(srv, __FILE__, __LINE__, "sbs", "WARNING: unknown config-key:", du->key, "(ignored)"); } } } if (srv->config_unsupported) { log_error_write(srv, __FILE__, __LINE__, "s", "Configuration contains unsupported keys. Going down."); } if (srv->config_deprecated) { log_error_write(srv, __FILE__, __LINE__, "s", "Configuration contains deprecated keys. Going down."); } if (srv->config_unsupported || srv->config_deprecated) { plugins_free(srv); network_close(srv); server_free(srv); return -1; } #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); sigaction(SIGUSR1, &act, NULL); # if defined(SA_SIGINFO) act.sa_sigaction = sigaction_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; # else act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; # endif sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGCHLD, &act, NULL); #elif defined(HAVE_SIGNAL) /* ignore the SIGPIPE from sendfile() */ signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGALRM, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGINT, signal_handler); #endif #ifdef USE_ALARM signal(SIGALRM, signal_handler); /* setup periodic timer (1 second) */ if (setitimer(ITIMER_REAL, &interval, NULL)) { log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed"); return -1; } getitimer(ITIMER_REAL, &interval); #endif #ifdef HAVE_FORK /* start watcher and workers */ num_childs = srv->srvconf.max_worker; if (num_childs > 0) { int child = 0; while (!child && !srv_shutdown && !graceful_shutdown) { if (num_childs > 0) { switch (fork()) { case -1: return -1; case 0: child = 1; break; default: num_childs--; break; } } else { int status; if (-1 != wait(&status)) { /** * one of our workers went away */ num_childs++; } else { switch (errno) { case EINTR: /** * if we receive a SIGHUP we have to close our logs ourself as we don't * have the mainloop who can help us here */ if (handle_sig_hup) { handle_sig_hup = 0; log_error_cycle(srv); /** * forward to all procs in the process-group * * we also send it ourself */ if (!forwarded_sig_hup) { forwarded_sig_hup = 1; kill(0, SIGHUP); } } break; default: break; } } } } /** * for the parent this is the exit-point */ if (!child) { /** * kill all children too */ if (graceful_shutdown) { kill(0, SIGINT); } else if (srv_shutdown) { kill(0, SIGTERM); } log_error_close(srv); network_close(srv); connections_free(srv); plugins_free(srv); server_free(srv); return 0; } } #endif if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) { log_error_write(srv, __FILE__, __LINE__, "s", "fdevent_init failed"); return -1; } /* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */ #ifdef HAVE_SIGACTION sigaction(SIGCHLD, &act, NULL); #elif defined(HAVE_SIGNAL) signal(SIGCHLD, signal_handler); #endif /* * kqueue() is called here, select resets its internals, * all server sockets get their handlers * * */ if (0 != network_register_fdevents(srv)) { plugins_free(srv); network_close(srv); server_free(srv); return -1; } /* might fail if user is using fam (not gamin) and famd isn't running */ if (NULL == (srv->stat_cache = stat_cache_init())) { log_error_write(srv, __FILE__, __LINE__, "s", "stat-cache could not be setup, dieing."); return -1; } #ifdef HAVE_FAM_H /* setup FAM */ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) { if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) { log_error_write(srv, __FILE__, __LINE__, "s", "could not open a fam connection, dieing."); return -1; } #ifdef HAVE_FAMNOEXISTS FAMNoExists(srv->stat_cache->fam); #endif srv->stat_cache->fam_fcce_ndx = -1; fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL); fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); } #endif /* get the current number of FDs */ srv->cur_fds = open("/dev/null", O_RDONLY); close(srv->cur_fds); for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno)); return -1; } } /* main-loop */ while (!srv_shutdown) { int n; size_t ndx; time_t min_ts; if (handle_sig_hup) { handler_t r; /* reset notification */ handle_sig_hup = 0; /* cycle logfiles */ switch(r = plugins_call_handle_sighup(srv)) { case HANDLER_GO_ON: break; default: log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r); break; } if (-1 == log_error_cycle(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying"); return -1; } else { #ifdef HAVE_SIGACTION log_error_write(srv, __FILE__, __LINE__, "sdsd", "logfiles cycled UID =", last_sighup_info.si_uid, "PID =", last_sighup_info.si_pid); #else log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled"); #endif } } if (handle_sig_alarm) { /* a new second */ #ifdef USE_ALARM /* reset notification */ handle_sig_alarm = 0; #endif /* get current time */ min_ts = time(NULL); if (min_ts != srv->cur_ts) { int cs = 0; connections *conns = srv->conns; handler_t r; switch(r = plugins_call_handle_trigger(srv)) { case HANDLER_GO_ON: break; case HANDLER_ERROR: log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed"); break; default: log_error_write(srv, __FILE__, __LINE__, "d", r); break; } /* trigger waitpid */ srv->cur_ts = min_ts; /* cleanup stat-cache */ stat_cache_trigger_cleanup(srv); /** * check all connections for timeouts * */ for (ndx = 0; ndx < conns->used; ndx++) { int changed = 0; connection *con; int t_diff; con = conns->ptr[ndx]; if (con->state == CON_STATE_READ || con->state == CON_STATE_READ_POST) { if (con->request_count == 1) { if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) { /* time - out */ #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - read-timeout:", con->fd); #endif connection_set_state(srv, con, CON_STATE_ERROR); changed = 1; } } else { if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) { /* time - out */ #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - read-timeout:", con->fd); #endif connection_set_state(srv, con, CON_STATE_ERROR); changed = 1; } } } if ((con->state == CON_STATE_WRITE) && (con->write_request_ts != 0)) { #if 0 if (srv->cur_ts - con->write_request_ts > 60) { log_error_write(srv, __FILE__, __LINE__, "sdd", "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts); } #endif if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) { /* time - out */ if (con->conf.log_timeouts) { log_error_write(srv, __FILE__, __LINE__, "sbsosds", "NOTE: a request for", con->request.uri, "timed out after writing", con->bytes_written, "bytes. We waited", (int)con->conf.max_write_idle, "seconds. If this a problem increase server.max-write-idle"); } connection_set_state(srv, con, CON_STATE_ERROR); changed = 1; } } if (con->state == CON_STATE_CLOSE && (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)) { changed = 1; } /* we don't like div by zero */ if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1; if (con->traffic_limit_reached && (con->conf.kbytes_per_second == 0 || ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) { /* enable connection again */ con->traffic_limit_reached = 0; changed = 1; } if (changed) { connection_state_machine(srv, con); } con->bytes_written_cur_second = 0; *(con->conf.global_bytes_per_second_cnt_ptr) = 0; #if 0 if (cs == 0) { fprintf(stderr, "connection-state: "); cs = 1; } fprintf(stderr, "c[%d,%d]: %s ", con->fd, con->fcgi.fd, connection_get_state(con->state)); #endif } if (cs == 1) fprintf(stderr, "\n"); } } if (srv->sockets_disabled) { /* our server sockets are disabled, why ? */ if ((srv->cur_fds + srv->want_fds < srv->max_fds * 8 / 10) && /* we have enough unused fds */ (srv->conns->used <= srv->max_conns * 9 / 10) && (0 == graceful_shutdown)) { for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); srv->sockets_disabled = 0; } } else { if ((srv->cur_fds + srv->want_fds > srv->max_fds * 9 / 10) || /* out of fds */ (srv->conns->used >= srv->max_conns) || /* out of connections */ (graceful_shutdown)) { /* graceful_shutdown */ /* disable server-fds */ for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); if (graceful_shutdown) { /* we don't want this socket anymore, * * closing it right away will make it possible for * the next lighttpd to take over (graceful restart) * */ fdevent_unregister(srv->ev, srv_socket->fd); close(srv_socket->fd); srv_socket->fd = -1; /* network_close() will cleanup after us */ if (srv->srvconf.pid_file->used && srv->srvconf.changeroot->used == 0) { if (0 != unlink(srv->srvconf.pid_file->ptr)) { if (errno != EACCES && errno != EPERM) { log_error_write(srv, __FILE__, __LINE__, "sbds", "unlink failed for:", srv->srvconf.pid_file, errno, strerror(errno)); } } } } } if (graceful_shutdown) { log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started"); } else if (srv->conns->used >= srv->max_conns) { log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached"); } else { log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds"); } srv->sockets_disabled = 1; } } if (graceful_shutdown && srv->conns->used == 0) { /* we are in graceful shutdown phase and all connections are closed * we are ready to terminate without harming anyone */ srv_shutdown = 1; } /* we still have some fds to share */ if (srv->want_fds) { /* check the fdwaitqueue for waiting fds */ int free_fds = srv->max_fds - srv->cur_fds - 16; connection *con; for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) { connection_state_machine(srv, con); srv->want_fds--; } } if ((n = fdevent_poll(srv->ev, 1000)) > 0) { /* n is the number of events */ int revents; int fd_ndx; #if 0 if (n > 0) { log_error_write(srv, __FILE__, __LINE__, "sd", "polls:", n); } #endif fd_ndx = -1; do { fdevent_handler handler; void *context; handler_t r; fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx); if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */ revents = fdevent_event_get_revent (srv->ev, fd_ndx); fd = fdevent_event_get_fd (srv->ev, fd_ndx); handler = fdevent_get_handler(srv->ev, fd); context = fdevent_get_context(srv->ev, fd); /* connection_handle_fdevent needs a joblist_append */ #if 0 log_error_write(srv, __FILE__, __LINE__, "sdd", "event for", fd, revents); #endif switch (r = (*handler)(srv, context, revents)) { case HANDLER_FINISHED: case HANDLER_GO_ON: case HANDLER_WAIT_FOR_EVENT: case HANDLER_WAIT_FOR_FD: break; case HANDLER_ERROR: /* should never happen */ SEGFAULT(); break; default: log_error_write(srv, __FILE__, __LINE__, "d", r); break; } } while (--n > 0); } else if (n < 0 && errno != EINTR) { log_error_write(srv, __FILE__, __LINE__, "ss", "fdevent_poll failed:", strerror(errno)); } for (ndx = 0; ndx < srv->joblist->used; ndx++) { connection *con = srv->joblist->ptr[ndx]; handler_t r; connection_state_machine(srv, con); switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: break; default: log_error_write(srv, __FILE__, __LINE__, "d", r); break; } con->in_joblist = 0; } srv->joblist->used = 0; } if (srv->srvconf.pid_file->used && srv->srvconf.changeroot->used == 0 && 0 == graceful_shutdown) { if (0 != unlink(srv->srvconf.pid_file->ptr)) { if (errno != EACCES && errno != EPERM) { log_error_write(srv, __FILE__, __LINE__, "sbds", "unlink failed for:", srv->srvconf.pid_file, errno, strerror(errno)); } } } #ifdef HAVE_SIGACTION log_error_write(srv, __FILE__, __LINE__, "sdsd", "server stopped by UID =", last_sigterm_info.si_uid, "PID =", last_sigterm_info.si_pid); #else log_error_write(srv, __FILE__, __LINE__, "s", "server stopped"); #endif /* clean-up */ log_error_close(srv); network_close(srv); connections_free(srv); plugins_free(srv); server_free(srv); return 0; }
int sap_server_register(const char *path, bdaddr_t *src) { sdp_record_t *record = NULL; GError *gerr = NULL; GIOChannel *io; if (sap_init() < 0) { error("Sap driver initialization failed."); return -1; } server = g_try_new0(struct sap_server, 1); if (!server) { sap_exit(); return -ENOMEM; } server->path = g_strdup(path); record = create_sap_record(SAP_SERVER_CHANNEL); if (!record) { error("Creating SAP SDP record failed."); goto sdp_err; } if (add_record_to_server(src, record) < 0) { error("Adding SAP SDP record to the SDP server failed."); sdp_record_free(record); goto sdp_err; } server->record_id = record->handle; io = bt_io_listen(BT_IO_RFCOMM, NULL, connect_confirm_cb, server, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_CHANNEL, SAP_SERVER_CHANNEL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH, BT_IO_OPT_MASTER, TRUE, BT_IO_OPT_INVALID); if (!io) { error("Can't listen at channel %d.", SAP_SERVER_CHANNEL); g_error_free(gerr); goto server_err; } DBG("Listen socket 0x%02x", g_io_channel_unix_get_fd(io)); server->listen_io = io; server->conn = NULL; if (!g_dbus_register_interface(connection, path, SAP_SERVER_INTERFACE, server_methods, server_signals, NULL, server, destroy_sap_interface)) { error("D-Bus failed to register %s interface", SAP_SERVER_INTERFACE); goto server_err; } return 0; server_err: remove_record_from_server(server->record_id); sdp_err: server_free(server); sap_exit(); return -1; }