void HandleSyscalls() { register int cnt; fd_set readfds; int nfds = -1; time_t periodic_interval_len = 20; /* secs, empirically found :) */ nfds = (RSC_SOCK > CLIENT_LOG ) ? (RSC_SOCK + 1) : (CLIENT_LOG + 1); init_user_ids(Proc->owner, NULL); set_user_priv(); dprintf(D_FULLDEBUG, "HandleSyscalls: about to chdir(%s)\n", Proc->iwd); if( chdir(Proc->iwd) < 0 ) { sprintf( ErrBuf, "Can't chdir() to \"%s\"! [%s(%d)]", Proc->iwd, strerror(errno), errno ); HadErr = TRUE; return; } dprintf(D_SYSCALLS, "Shadow: Starting to field syscall requests\n"); errno = 0; time_t current_time = time(0); time_t next_periodic_update = current_time + periodic_interval_len; for(;;) { /* get a request and fulfill it */ FD_ZERO(&readfds); FD_SET(RSC_SOCK, &readfds); FD_SET(CLIENT_LOG, &readfds); struct timeval *ptimer = NULL, timer; timer.tv_sec = next_periodic_update - current_time; timer.tv_usec = 0; ptimer = &timer; /* if the current timer is set for a time longer than this, than truncate the timer required to the periodic limit. After inspection of the bandwidth timer, it seems that it will recorrect itself if select comes out of the loop before the timer goes off anyway to handle syscalls */ if ( timer.tv_sec > periodic_interval_len) { timer.tv_sec = next_periodic_update - current_time; ptimer = &timer; } unblock_signal(SIGCHLD); unblock_signal(SIGUSR1); #if defined(LINUX) || defined(Solaris) cnt = select(nfds, &readfds, (fd_set *)0, (fd_set *)0, ptimer); #else cnt = select(nfds, &readfds, 0, 0, ptimer); #endif block_signal(SIGCHLD); block_signal(SIGUSR1); if( cnt < 0 && errno != EINTR ) { EXCEPT("HandleSyscalls: select: errno=%d, rsc_sock=%d, client_log=%d",errno,RSC_SOCK,CLIENT_LOG); } if( cnt < 0 && errno == EINTR ) { continue; } if( FD_ISSET(CLIENT_LOG, &readfds) ) { if( HandleLog() < 0 ) { EXCEPT( "Peer went away" ); } } if( FD_ISSET(RSC_SOCK, &readfds) ) { if( do_REMOTE_syscall() < 0 ) { dprintf(D_SYSCALLS, "Shadow: do_REMOTE_syscall returned < 0\n"); break; } } if( FD_ISSET(UMBILICAL, &readfds) ) { dprintf(D_ALWAYS, "Shadow: Local scheduler apparently died, so I die too\n"); exit(1); } current_time = time(0); /* if this is true, then do the periodic_interval_len events */ if (current_time >= next_periodic_update) { next_periodic_update = current_time + periodic_interval_len; /* evaluate some attributes for policies like determining what to do if a job suspends wierdly or some such thing. This function has the possibility of making the shadow exit with JOB_SHOULD_HOLD or futzing up some global variables about how the job could've exited and letting Wraup take care of it. */ if (periodic_policy() == true) { break; } } #if defined(SYSCALL_DEBUG) strcpy( SyscallLabel, "shadow" ); #endif } /* The user job might exit while there is still unread data in the log. So, select with a timeout of zero, and flush everything from the log. */ /* NOTE: Since HandleLog does it's own loop to make sure it's read everything, we don't need a loop here, and should only call HandleLog once. In fact, if there's a problem w/ select(), a loop here can cause an infinite loop. -Derek Wright and Jim Basney, 2/17/99. */ HandleLog(); /* Take back normal condor privileges */ set_condor_priv(); /* If we are debugging with named pipes as our communications medium, won't have a condor_startd running - don't try to send to it. */ if( !UsePipes ) { send_quit( ExecutingHost, GlobalCap ); } dprintf(D_ALWAYS, "Shadow: Job %d.%d exited, termsig = %d, coredump = %d, retcode = %d\n", Proc->id.cluster, Proc->id.proc, WTERMSIG(JobStatus), WCOREDUMP(JobStatus), WEXITSTATUS(JobStatus)); }
/*---------------------------------------------------------------------------------------------------------------------- | This function provides the ability to read everything following the block name (which is read by the NxsReader | object) to the END or ENDBLOCK statement. Characters are read from the input stream `in'. Overrides the virtual | function in the base class. */ void GarliReader::Read( NxsToken &token) /* the token used to read from `in' */ { isEmpty = false; // This should be the semicolon after the block name // token.GetNextToken(); if (!token.Equals(";")) { errormsg = "Expecting ';' after "; errormsg += id; errormsg += " block name, but found "; errormsg += token.GetToken(); errormsg += " instead"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } for (;;) { token.GetNextToken(); if (token.Abbreviation("ENdblock")) { HandleEndblock(token); break; } else if (token.Abbreviation("GarliReader")) { HandleGarliReader(token); } else if (token.Abbreviation("Help")) { HandleHelp(token); } else if (token.Abbreviation("Log")) { HandleLog(token); } else if (token.Abbreviation("EXecute")) { HandleExecute(token); } else if (token.Abbreviation("Show")) { HandleShow(token); } else if (token.Abbreviation("Quit")) { quit_now = true; message = "\nGarliReader says goodbye\n"; PrintMessage(); break; } else { SkippingCommand(token.GetToken()); do { token.GetNextToken(); } while (!token.AtEOF() && !token.Equals(";")); if (token.AtEOF()) { errormsg = "Unexpected end of file encountered"; throw NxsException(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn()); } } } }