int datastream_destroy (datastream_t *datastream) { int error; if (unlikely(datastream == NULL)) LOG_ERROR_AND_RETURN(-1, "null datasttream_t"); if (datastream->queue.count != 0) LOG3("queue is not empty! [count=%llu]", datastream->queue.count); if (unlikely(0 != (error = flist_destroy(&datastream->queue)))) LOG_ERROR_AND_RETURN(-101, "failed to flist_destroy, %d", error); if (datastream->data != NULL) { free(datastream->data); datastream->data = NULL; } if (unlikely(0 != (error = thread_destroy(&datastream->thread)))) LOG_ERROR_AND_RETURN(-101, "failed to thread_destroy, %d", error); return 0; }
static void mapidcom() //Communicates with clients through IPC { fd_set active_fd_set; // active file descriptor list fd_set read_fd_set; // temp file descriptor list for select() int fdmax; // maximum file descriptor number int yes = 1; // for setsockopt() SO_REUSEADDR, below struct sockaddr_un mapidaddr; struct sockaddr_un remoteaddr; struct mapiipcbuf qbuf; socklen_t addrlen; int nbytes, len, s; struct client *cl= NULL; flist_node_t *tmpnode; conf_category_entry_t *cat=NULL; char *local; struct group *mapi_group; conf_category_t *conf; mapidsocket=strdup(MAPIDSOCKGLOBAL); if ((conf = pc_load(mapid_conf)) != NULL) { cat = pc_get_category(conf, ""); local=pc_get_param(cat, "local"); if (local!=NULL && strcmp(local, "1")==0) { free(mapidsocket); mapidsocket=printf_string(MAPIDSOCKHOME, getenv("HOME") ); } pc_close(conf); } // create the listener socket if ((listenerfd = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { DEBUG_CMD(Debug_Message("ERROR: socket: %s", strerror(errno))); exit(EXIT_FAILURE); } // avoid "address already in use" error message if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { DEBUG_CMD(Debug_Message("ERROR: setsockopt: %s", strerror(errno))); exit(EXIT_FAILURE); } // set up the address we will be binding to memset(&mapidaddr, 0, sizeof (mapidaddr)); mapidaddr.sun_family = AF_LOCAL; memcpy(mapidaddr.sun_path, mapidsocket, strlen(mapidsocket)+1); unlink(mapidsocket); len = sizeof mapidaddr.sun_family + strlen(mapidaddr.sun_path); if (bind(listenerfd, (struct sockaddr *) &mapidaddr, len)) { DEBUG_CMD(Debug_Message("ERROR: bind: %s", strerror(errno))); exit(EXIT_FAILURE); } // allow any member of our own group to connect chmod(mapidsocket, S_IRWXU | S_IRWXG); // if a mapi user group exists, set group permissions accordingly, // otherwise the group ID will be equal to the user ID of the user that // invoked mapid mapi_group = getgrnam(MAPI_GROUP_NAME); if (mapi_group != NULL) { chown(mapidsocket, -1, mapi_group->gr_gid); } if (listen(listenerfd, BACKLOG) == -1) { DEBUG_CMD(Debug_Message("ERROR: listen: %s", strerror(errno))); exit(EXIT_FAILURE); } FD_ZERO (&active_fd_set); // add the listener to the active set FD_SET (listenerfd, &active_fd_set) ; // keep track of the biggest file descriptor fdmax = listenerfd; // so far, it's just this one // wait for commands from the mapi stub, for ever... while (1) { read_fd_set = active_fd_set; // copy it if (select(fdmax + 1, &read_fd_set, NULL, NULL, NULL) == -1) { DEBUG_CMD(Debug_Message("ERROR: select: %s", strerror(errno))); break; } // run through the existing connections for (s = 0; s <= fdmax; s++) { if (FD_ISSET (s, &read_fd_set)) { // connection on the original listener socket if (s == listenerfd) { addrlen = sizeof (remoteaddr); if ((newfd = accept(listenerfd, (struct sockaddr *) &remoteaddr, &addrlen)) == -1) { DEBUG_CMD(Debug_Message("accept: %s", strerror(errno))); } else { FD_SET (newfd, &active_fd_set) ; // add to active set if (newfd > fdmax) { // keep track of the maximum fdmax = newfd; } } } // handle data from an existing client else { if ((nbytes = recv (s, &qbuf, MAX_SEND_SIZE, 0)) <= 0) { if (nbytes == 0) { // connection closed - find client's pid while(__sync_lock_test_and_set(&clientlist_lock,1)); tmpnode = (flist_node_t *) flist_head (clientlist); cl = NULL; while (tmpnode != NULL) { if (((struct client *) tmpnode->data)->sock == s) { cl = (struct client *) tmpnode->data; break; } tmpnode = flist_next (tmpnode); } clientlist_lock = 0; if (cl == NULL) {/* This is not interesting, as it will occur upon requests from clients without flows etc. WARNING_CMD (printf ("WARNING: Zero bytes from socket %d [%s:%d]\n", s, __FILE__, __LINE__)); */ /* shouldn't really exit here? * this will cause the program to exit on errors with an empty * client-list which isn't really an error (IMHO) */ //exit(EXIT_FAILURE); } else { while(__sync_lock_test_and_set(&clientlist_lock,1)); //clean up any remaining flows tmpnode = (flist_node_t *) flist_head (cl->flowlist); while (tmpnode != NULL) { cleanup_flow ((struct flow *) tmpnode->data); tmpnode = flist_next (tmpnode); } tmpnode = (flist_node_t *) flist_head (cl->devicelist); while (tmpnode != NULL) { mapidrv_delete_device = get_drv_funct (tmpnode->data, "mapidrv_delete_device"); mapidrv_delete_device (tmpnode->id); tmpnode = flist_next (tmpnode); } flist_destroy (cl->flowlist); flist_destroy (cl->devicelist); free(cl->devicelist); free (cl->flowlist); //remove this client from global client list free(flist_remove (clientlist, cl->pid)); clientlist_lock = 0; } } else { DEBUG_CMD(Debug_Message("WARNING: recv: %s at", strerror (errno))); } close (s); FD_CLR (s, &active_fd_set); // remove it from active set } else { // we got some data from a client: process request switch (qbuf.cmd) { case GET_LIBS: cmd_get_libs (qbuf.pid, s); break; case GET_LIBPATH: cmd_get_libpath (qbuf.pid, s); break; case CREATE_FLOW: cmd_create_flow ((char *)qbuf.data, qbuf.pid, qbuf.uid, s); break; case CLOSE_FLOW: cmd_close_flow (qbuf.fd, qbuf.pid, s, 1); break; case GET_FLOW_INFO: cmd_get_flow_info (qbuf.fd, qbuf.pid, s); break; case GET_FUNCTION_INFO: cmd_get_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s); break; case GET_NEXT_FUNCTION_INFO: cmd_get_next_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s); break; case GET_NEXT_FLOW_INFO: cmd_get_next_flow_info (qbuf.fd, qbuf.pid, s); break; case GET_NEXT_DEVICE_INFO: cmd_get_next_device_info (qbuf.fd, qbuf.pid, s); break; case GET_DEVICE_INFO: cmd_get_device_info (qbuf.fd, qbuf.pid, s); break; case MAPI_STATS: cmd_stats ((char *)qbuf.data, qbuf.pid, qbuf.uid, s); break; case APPLY_FUNCTION: cmd_apply_function (&qbuf, qbuf.pid, s); break; case READ_RESULT: cmd_read_results (qbuf.fd, qbuf.fid, qbuf.pid, s); break; case CONNECT: cmd_connect (qbuf.fd, qbuf.pid, s); break; case CREATE_FLOW_ACK: case APPLY_FUNCTION_ACK: case READ_RESULT_ACK: case CONNECT_ACK: case CLOSE_FLOW_ACK: case SET_AUTHDATA_ACK: break; case READ_ERROR_ACK: break; case ERROR_ACK: break; case CREATE_OFFLINE_DEVICE: cmd_create_offline_device ((char *)qbuf.data, qbuf.fid, qbuf.pid, s); break; case CREATE_OFFLINE_DEVICE_ACK: break; case START_OFFLINE_DEVICE: cmd_start_offline_device ((char *)qbuf.data, qbuf.pid, s); break; case START_OFFLINE_DEVICE_ACK: break; case DELETE_OFFLINE_DEVICE: cmd_delete_offline_device ((char *)qbuf.data, qbuf.pid, s); break; case DELETE_OFFLINE_DEVICE_ACK: break; case CREATE_OFFLINE_FLOW_ACK: break; case LOAD_LIBRARY: cmd_load_library ((char *)qbuf.data, qbuf.pid, s); default: break; } } } } } // for } // while(1) }
static void mapid_shutdown(int data) { flist_node_t *cur; struct client *cl; mapidrv *drv = drvlist; /* espenb TODO: use lock mechanisms instead * each thread receives signals, only one thread must execute * shutdown, only one shutdown necessary */ if (running_shutdown != 0) return; running_shutdown = 1; //we don't want funny things to happen while freeing memory signal(SIGTERM, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); printf("Closing operations\n"); //Unload drivers while (drv) { drvlist = drvlist->next; mapidrv_delete_device = get_drv_funct(drv->handle, "mapidrv_delete_device"); if (mapidrv_delete_device) mapidrv_delete_device(drv->devid); /* if we close, we lose the symbol information associated with drivers * when running valgrind. */ #ifndef VALGRIND printf("!!dlclose\n"); dlclose(drv->handle); #endif free(drv->device); if (drv->description!=NULL) free(drv->description); if (drv->name) free(drv->name); //if(drv->alias != NULL) //free(drv->alias); free(drv); drv = drvlist; } //Remove flowlist flist_destroy(flowlist); free(flowlist); //Remove clientlist cur = flist_head(clientlist); while (cur) { cl = flist_data(cur); flist_destroy(cl->flowlist); free(cl->flowlist); cur = flist_next(cur); } flist_destroy(clientlist); free(clientlist); free(gflist->fflist); free(gflist); free(mapidsocket); free(mapid_conf); if (log_to_file) { daemon_terminated(log_fd_info, "MAPID", daemonize, 0); daemon_terminated(log_fd_debug, "MAPID", daemonize, 0); } if (log_to_syslog) { log_message("MAPID was terminated %s%s", daemonize ? " ( was running as daemon )" : ""); closelog(); // closes the descriptor being used to write to the system logger } //release socket resources unlink(mapidsocket); close(listenerfd); close(newfd); running_shutdown = 2; printf("mapid terminated\n"); exit((data == 0) ? EXIT_FAILURE : EXIT_SUCCESS); }