static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, read_link(dentry)); return NULL; }
static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, read_link(dentry)); return 0; }
void update_links( void ) { char_data* ch; link_data* link; text_data* receive; fd_set read_set; fd_set write_set; fd_set exec_set; struct timeval start; struct timeval timeout; gettimeofday( &start, NULL ); timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO( &read_set ); FD_ZERO( &write_set ); FD_ZERO( &exec_set ); FD_SET( socket_one, &read_set ); FD_SET( socket_two, &read_set ); for( link = link_list; link != NULL; link = link->next ) { FD_SET( link->channel, &read_set ); FD_SET( link->channel, &write_set ); FD_SET( link->channel, &exec_set ); } if( (int) select( FD_SETSIZE, &read_set, &write_set, &exec_set, &timeout ) < 0 ) panic( "Update links: select" ); if( FD_ISSET( socket_one, &read_set ) ) open_link( socket_one ); if( FD_ISSET( socket_two, &read_set ) ) open_link( socket_two ); for( link = link_list; link != NULL; link = link_next ) { link_next = link->next; if( FD_ISSET( link->channel, &exec_set ) ) { write( link->player ); close_socket( link ); continue; } if( FD_ISSET( link->channel, &read_set ) ) { link->idle = 0; if( link->player != NULL ) link->player->timer = current_time; if( !read_link( link ) ) { write( link->player ); close_socket( link ); continue; } } if( link->idle++ > 10000 && link->connected != CON_PLAYING ) { send( link, "\n\r\n\r-- CONNECTION TIMEOUT --\n\r" ); close_socket( link, TRUE ); } } pulse_time[ TIME_READ_INPUT ] = stop_clock( start ); gettimeofday( &start, NULL ); for( link = link_list; link != NULL; link = link_next ) { link_next = link->next; if( link->command = ( ( receive = link->receive ) != NULL ) ) { ampersand( receive ); link->receive = receive->next; link->idle = 0; if( link->connected == CON_PLAYING ) { stop_idling( ch = link->character ); interpret( link->character, receive->message.text ); } else nanny( link, receive->message.text ); delete receive; } } pulse_time[ TIME_COMMANDS ] = stop_clock( start ); gettimeofday( &start, NULL ); for( link = link_list; link != NULL; link = link_next ) { link_next = link->next; if( link->idle%25 == 0 && FD_ISSET( link->channel, &write_set ) && !process_output( link ) ) { write( link->player ); close_socket( link ); } } pulse_time[ TIME_WRITE_OUTPUT ] = stop_clock( start ); return; }
void impl_init(void) { const char* mode_env = getenv("HUPTIME_MODE"); const char* multi_env = getenv("HUPTIME_MULTI"); const char* revive_env = getenv("HUPTIME_REVIVE"); const char* debug_env = getenv("HUPTIME_DEBUG"); const char* pipe_env = getenv("HUPTIME_PIPE"); const char* wait_env = getenv("HUPTIME_WAIT"); if( debug_env != NULL && strlen(debug_env) > 0 ) { debug_enabled = !strcasecmp(debug_env, "true") ? TRUE: FALSE; } DEBUG("Initializing..."); /* Initialize our lock. */ impl_init_lock(); /* Save this pid as our master pid. * This is done to handle processes that use * process pools. We remember the master pid and * will do the full fork()/exec() only when we are * the master. Otherwise, we will simply shutdown * gracefully, and all the master to restart. */ master_pid = getpid(); /* Grab our exit strategy. */ if( mode_env != NULL && strlen(mode_env) > 0 ) { if( !strcasecmp(mode_env, "fork") ) { exit_strategy = FORK; DEBUG("Exit strategy is fork."); } else if( !strcasecmp(mode_env, "exec") ) { exit_strategy = EXEC; DEBUG("Exit strategy is exec."); } else { fprintf(stderr, "Unknown exit strategy."); libc.exit(1); } } /* Check if we have something to unlink. */ to_unlink = getenv("HUPTIME_UNLINK"); if( to_unlink != NULL && strlen(to_unlink) > 0 ) { DEBUG("Unlink is '%s'.", to_unlink); } /* Clear up any outstanding child processes. * Because we may have exited before the process * could do appropriate waitpid()'s, we try to * clean up children here. Note that we may have * some zombies that hang around during the life * of the program, but at every restart they will * be cleaned up (so at least they won't grow * without bound). */ int status = 0; while( waitpid((pid_t)-1, &status, WNOHANG) > 0 ); /* Check if we're in multi mode. */ if( multi_env != NULL && strlen(multi_env) > 0 ) { multi_mode = !strcasecmp(multi_env, "true") ? TRUE: FALSE; } #ifndef SO_REUSEPORT if( multi_mode == TRUE ) { fprintf(stderr, "WARNING: Multi mode not supported.\n"); fprintf(stderr, "(Requires at least Linux 3.9 and recent headers).\n"); } #endif /* Check if we're in revive mode. */ if( revive_env != NULL && strlen(revive_env) > 0 ) { revive_mode = !strcasecmp(revive_env, "true") ? TRUE : FALSE; } /* Check if we are in wait mode. */ if( wait_env != NULL && strlen(wait_env) > 0 ) { wait_mode = !strcasecmp(wait_env, "true") ? TRUE : FALSE; } /* Check if we're a respawn. */ if( pipe_env != NULL && strlen(pipe_env) > 0 ) { int fd = -1; fdinfo_t *info = NULL; int pipefd = strtol(pipe_env, NULL, 10); DEBUG("Loading all file descriptors."); /* Decode all passed information. */ while( !info_decode(pipefd, &fd, &info) ) { fd_save(fd, info); DEBUG("Decoded fd %d (type %d).", fd, info->type); info = NULL; } if( info != NULL ) { dec_ref(info); } /* Finished with the pipe. */ libc.close(pipefd); unsetenv("HUPTIME_PIPE"); DEBUG("Finished decoding."); /* Close all non-encoded descriptors. */ for( fd = 0; fd < fd_max(); fd += 1 ) { info = fd_lookup(fd); if( info == NULL ) { DEBUG("Closing fd %d.", fd); libc.close(fd); } } /* Restore all given file descriptors. */ for( fd = 0; fd < fd_limit(); fd += 1 ) { info = fd_lookup(fd); if( info != NULL && info->type == SAVED ) { fdinfo_t *orig_info = fd_lookup(info->saved.fd); if( orig_info != NULL ) { /* Uh-oh, conflict. Move the original (best effort). */ do_dup(info->saved.fd); do_close(info->saved.fd); } /* Return the offset (ignore failure). */ if( info->saved.offset != (off_t)-1 ) { lseek(fd, info->saved.offset, SEEK_SET); } /* Move the SAVED fd back. */ libc.dup2(fd, info->saved.fd); DEBUG("Restored fd %d.", info->saved.fd); } } } else { DEBUG("Saving all initial file descriptors."); /* Save all of our initial files. These are used * for re-execing the process. These are persisted * effectively forever, and on restarts we close * everything that is not a BOUND socket or a SAVED * file descriptor. */ for( int fd = 0; fd < fd_max(); fd += 1 ) { fdinfo_t *info = fd_lookup(fd); if( info != NULL ) { /* Encoded earlier. */ continue; } /* Make a new SAVED FD. */ int newfd = libc.dup(fd); if( newfd >= 0 ) { fdinfo_t *saved_info = alloc_info(SAVED); if( saved_info != NULL ) { saved_info->saved.fd = fd; saved_info->saved.offset = lseek(fd, 0, SEEK_CUR); fd_save(newfd, saved_info); DEBUG("Saved fd %d (offset %lld).", fd, (long long int)saved_info->saved.offset); } } } } /* Save the environment. * * NOTE: We reserve extra space in the environment * for our special start-up parameters, which will be added * in impl_exec() below. (The encoded BOUND/SAVED sockets). * * We also filter out the special variables above that were * used to pass in information about sockets that were bound. */ free(environ_copy); environ_copy = (char**)read_nul_sep("/proc/self/environ"); DEBUG("Saved environment."); /* Save the arguments. */ free(args_copy); args_copy = (char**)read_nul_sep("/proc/self/cmdline"); DEBUG("Saved args."); for( int i = 0; args_copy[i] != NULL; i += 1 ) { DEBUG(" arg%d=%s", i, args_copy[i]); } /* Save the cwd & exe. */ free(cwd_copy); cwd_copy = (char*)read_link("/proc/self/cwd"); DEBUG("Saved cwd."); free(exe_copy); exe_copy = (char*)read_link("/proc/self/exe"); DEBUG("Saved exe."); /* Install our signal handlers. */ impl_install_sighandlers(); /* Initialize our thread. */ impl_init_thread(); /* Unblock our signals. * Note that we have specifically masked the * signals prior to the exec() below, to cover * the race between program start and having * installed the appropriate handlers. */ sigset_t set; sigemptyset(&set); sigaddset(&set, SIGHUP); sigprocmask(SIG_UNBLOCK, &set, NULL); /* Done. */ DEBUG("Initialization complete."); }
static mrb_value read_value(MarshalContext *ctx) { mrb_state *mrb = ctx->mrb; char type = ctx->readByte(); mrb_value value; if (mrb->arena_idx > maxArena) maxArena = mrb->arena_idx; int arena = mrb_gc_arena_save(mrb); switch (type) { case TYPE_NIL : value = mrb_nil_value(); break; case TYPE_TRUE : value = mrb_true_value(); break; case TYPE_FALSE : value = mrb_false_value(); break; case TYPE_FIXNUM : value = mrb_fixnum_value(read_fixnum(ctx)); break; case TYPE_BIGNUM : value = mrb_fixnum_value(read_bignum(ctx)); break; case TYPE_FLOAT : value = mrb_float_value(mrb, read_float(ctx)); ctx->objects.add(value); break; case TYPE_STRING : value = read_string_value(ctx); ctx->objects.add(value); break; case TYPE_ARRAY : value = read_array(ctx); break; case TYPE_HASH : value = read_hash(ctx); break; case TYPE_SYMBOL : value = mrb_symbol_value(read_symbol(ctx)); break; case TYPE_SYMLINK : value = mrb_symbol_value(read_symlink(ctx)); break; case TYPE_OBJECT : value = read_object(ctx); break; case TYPE_IVAR : value = read_instance_var(ctx); break; case TYPE_LINK : value = read_link(ctx); break; case TYPE_USERDEF : value = read_userdef(ctx); ctx->objects.add(value); break; default : CCLOG( "Marshal.load: unsupported value type '%c',gbufsize %d",type,g_buf_size); CCAssert(false,"f**k"); //exit(0); } mrb_gc_arena_restore(mrb, arena); return value; }