bool ltr_int_master(bool standalone) { current_pose.pose.pitch = 0.0; current_pose.pose.yaw = 0.0; current_pose.pose.roll = 0.0; current_pose.pose.tx = 0.0; current_pose.pose.ty = 0.0; current_pose.pose.tz = 0.0; current_pose.pose.counter = 0; current_pose.pose.status = STOPPED; current_pose.blobs = 0; gui_shutdown_request = false; int socket; save_prefs = standalone; if(standalone) { //Detach from the caller, retaining stdin/out/err // Does weird things to gui ;) if(daemon(0, 1) != 0) { return false; } if(!ltr_int_gui_lock(false)) { ltr_int_log_message("Gui is active, quitting!\n"); return true; } socket = ltr_int_create_server_socket(ltr_int_master_socket_name()); } else { if(!ltr_int_gui_lock(true)) { ltr_int_log_message("Couldn't lock gui lockfile!\n"); return false; } int counter = 10; while((socket = ltr_int_create_server_socket(ltr_int_master_socket_name())) <= 0) { if((counter--) <= 0) { ltr_int_log_message("The other master doesn't give up!\n"); return false; } sleep(1); } ltr_int_log_message("Other master gave up, gui master taking over!\n"); } if(socket < 0) { ltr_int_log_message("Master already running, quitting!\n"); return true; } ltr_int_log_message("Starting as master!\n"); if(ltr_int_init() != 0) { ltr_int_log_message("Could not initialize tracking!\n"); ltr_int_log_message("Closing socket %d\n", socket); close(socket); unlink(ltr_int_master_socket_name()); return false; } ltr_int_register_cbk(ltr_int_new_frame, NULL, ltr_int_state_changed, NULL); ltr_int_master_main_loop(socket); ltr_int_log_message("Shutting down tracking!\n"); ltr_int_shutdown(); ltr_int_log_message("Master closing socket %d\n", socket); close(socket); unlink(ltr_int_master_socket_name()); ltr_int_gui_lock_clean(); int cntr = 10; while((ltr_int_get_tracking_state() != STOPPED) && (cntr > 0)) { --cntr; ltr_int_log_message("Tracker not stopped yet, waiting for the stop...\n"); sleep(1); } ltr_int_gui_lock_clean(); if(standalone) { ltr_int_free_prefs(); } return true; }
static void *ltr_int_slave_reader_thread(void *param) { ltr_int_log_message("Slave reader thread function entered!\n"); (void) param; int received_frames = 0; master_works = false; while(1){ if(!ltr_int_try_start_master(&master_uplink, &master_downlink)){ break; } ltr_int_log_message("Master Uplink %d, Downlink %d\n", master_uplink, master_downlink); int poll_errs = 0; struct pollfd downlink_poll= { .fd = master_downlink, .events = POLLIN, .revents = 0 }; while(1){ downlink_poll.events = POLLIN; int fds = poll(&downlink_poll, 1, 1000); if(fds < 0){ ++poll_errs; ltr_int_my_perror("poll"); if(poll_errs > 3){break;}else{continue;} }else if(fds == 0){ if(!parent_alive()){ //printf("Parent %lu died! (1)\n", (unsigned long)ppid); return NULL; } continue; } if(downlink_poll.revents & POLLHUP){ break; } //We have a new message if(ltr_int_process_message(master_downlink)){ ++received_frames; if(received_frames > 20){ master_works = true; } } if(!parent_alive()){ //printf("Parent %lu died! (2)\n", (unsigned long)ppid); return NULL; } } } return NULL; } static void ltr_int_slave_main_loop() { //Prepare to process client requests struct ltr_comm *com = mmm.data; ltr_cmd cmd = NOP_CMD; bool recenter = false; bool quit_flag = false; while(!quit_flag){ if((com->cmd != NOP_CMD) || com->recenter || com->notify){ ltr_int_lockSemaphore(mmm.sem); cmd = (ltr_cmd)com->cmd; com->cmd = NOP_CMD; recenter = com->recenter; notify = com->notify; com->recenter = false; ltr_int_unlockSemaphore(mmm.sem); } int res = 0; do{ switch(cmd){ case PAUSE_CMD: res = ltr_int_send_message(master_uplink, CMD_PAUSE, 0); break; case RUN_CMD: res = ltr_int_send_message(master_uplink, CMD_WAKEUP, 0); break; case STOP_CMD: quit_flag = true; break; case FRAMES_CMD: res = ltr_int_send_message(master_uplink, CMD_FRAMES, 0); break; default: break; } if(res < 0){ usleep(100000); } if(!parent_alive()){ //printf("Parent %lu died! (3)\n", (unsigned long)ppid); break; } }while((res < 0) && (!quit_flag)); cmd = NOP_CMD; if(recenter){ ltr_int_log_message("Slave sending master recenter request!\n"); if(ltr_int_send_message(master_uplink, CMD_RECENTER, 0) >= 0){ //clear request only on successfull transmission recenter = false; } } if(!parent_alive()){ //printf("Parent %lu died! (3)\n", (unsigned long)ppid); break; } usleep(100000); } } //main slave function bool ltr_int_slave(const char *c_profile, const char *c_com_file, const char *ppid_str, const char *close_pipe_str, const char *notify_pipe_str) { unsigned long tmp_ppid; profile_name = ltr_int_my_strdup(c_profile); sscanf(ppid_str, "%lu", &tmp_ppid); int tmp_pipe = -1; sscanf(close_pipe_str, "%d", &tmp_pipe); if(tmp_pipe > 0){ close(tmp_pipe); } sscanf(notify_pipe_str, "%d", ¬ify_pipe); if(notify_pipe > 0){ fcntl(notify_pipe, F_SETFL, fcntl(notify_pipe, F_GETFL) | O_NONBLOCK); } //printf("Going to monitor parent %lu!\n", tmp_ppid); ppid = (pid_t)tmp_ppid; if(!ltr_int_read_prefs(NULL, false)){ ltr_int_log_message("Couldn't load preferences!\n"); return false; } ltr_int_init_axes(&axes, profile_name); //Prepare client comm channel char *com_file = ltr_int_my_strdup(c_com_file); if(!ltr_int_mmap_file(com_file, sizeof(struct ltr_comm), &mmm)){ ltr_int_log_message("Couldn't mmap file!!!\n"); return false; } free(com_file); if(pthread_create(&reader_tid, NULL, ltr_int_slave_reader_thread, NULL) == 0){ ltr_int_slave_main_loop(); pthread_join(reader_tid, NULL); } close_master_comms(&master_uplink, &master_downlink); ltr_int_unmap_file(&mmm); //finish prefs ltr_int_close_axes(&axes); ltr_int_free_prefs(); free(profile_name); ltr_int_gui_lock_clean(); close(notify_pipe); return true; }