int ScriptProc::StartJob() { dprintf(D_FULLDEBUG,"in ScriptProc::StartJob()\n"); if ( !JobAd ) { dprintf ( D_ALWAYS, "No JobAd in ScriptProc::StartJob()!\n" ); return 0; } MyString attr; attr = name; attr += ATTR_JOB_CMD; char* tmp = NULL; if( ! JobAd->LookupString( attr.Value(), &tmp ) ) { dprintf( D_ALWAYS, "%s not found in JobAd. Aborting StartJob.\n", attr.Value() ); return 0; } // // // // // // // executable // // // // // // // TODO: make it smart in cases we're not the gridshell and/or // didn't transfer files so that we don't prepend the wrong // path to the binary, and don't try to chmod it. MyString exe_path = Starter->GetWorkingDir(); exe_path += DIR_DELIM_CHAR; exe_path += tmp; free( tmp ); tmp = NULL; if( Starter->isGridshell() ) { // if we're a gridshell, chmod() the binary, since globus // probably transfered it for us and left it with bad // permissions... priv_state old_priv = set_user_priv(); int retval = chmod( exe_path.Value(), 0755 ); set_priv( old_priv ); if( retval < 0 ) { dprintf( D_ALWAYS, "Failed to chmod %s: %s (errno %d)\n", exe_path.Value(), strerror(errno), errno ); return 0; } } // // // // // // // Args // // // // // // char *args1 = NULL; char *args2 = NULL; MyString args1_attr; MyString args2_attr; args1_attr = name; args1_attr += ATTR_JOB_ARGUMENTS1; args2_attr = name; args2_attr += ATTR_JOB_ARGUMENTS2; JobAd->LookupString(args1_attr.Value(), &args1); JobAd->LookupString(args2_attr.Value(), &args2); ArgList args; // Since we are adding to the argument list, we may need to deal // with platform-specific arg syntax in the user's args in order // to successfully merge them with the additional args. args.SetArgV1SyntaxToCurrentPlatform(); // First, put "condor_<name>script" at the front of Args, // since that will become argv[0] of what we exec(), either // the wrapper or the actual job. MyString arg0; arg0 = "condor_"; arg0 += name; arg0 += "script"; args.AppendArg(arg0.Value()); MyString args_error; if(args2 && *args2) { args.AppendArgsV2Raw(args2,&args_error); } else if(args1 && *args1) { args.AppendArgsV1Raw(args1,&args_error); } else { dprintf( D_FULLDEBUG, "neither %s nor %s could be found in JobAd\n", args1_attr.Value(), args2_attr.Value()); } free( args1 ); free( args2 ); // // // // // // // Environment // // // // // // char *env1 = NULL; char *env2 = NULL; MyString env1_attr; MyString env2_attr; env1_attr = name; env1_attr += ATTR_JOB_ENVIRONMENT1; env2_attr = name; env2_attr += ATTR_JOB_ENVIRONMENT2; JobAd->LookupString( env1_attr.Value(), &env1 ); JobAd->LookupString( env2_attr.Value(), &env2 ); // TODO do we want to use the regular ATTR_JOB_ENVIRONMENT // if there's nothing specific for this script? // Now, instantiate an Env object so we can manipulate the // environment as needed. Env job_env; MyString env_errors; if( env2 && *env2 ) { if( ! job_env.MergeFromV2Raw(env2,&env_errors) ) { dprintf( D_ALWAYS, "Invalid %s found in JobAd (%s). " "Aborting ScriptProc::StartJob.\n", env2_attr.Value(),env_errors.Value() ); free( env1 ); free( env2 ); return 0; } } else if( env1 && *env1 ) { if( ! job_env.MergeFromV1Raw(env1,&env_errors) ) { dprintf( D_ALWAYS, "Invalid %s found in JobAd (%s). " "Aborting ScriptProc::StartJob.\n", env1_attr.Value(),env_errors.Value() ); free( env1 ); free( env2 ); return 0; } } free(env1); free(env2); // Now, let the starter publish any env vars it wants to add Starter->PublishToEnv( &job_env ); // TODO: Deal with port regulation stuff? // Grab the full environment back out of the Env object if(IsFulldebug(D_FULLDEBUG)) { MyString env_str; job_env.getDelimitedStringForDisplay(&env_str); dprintf(D_FULLDEBUG, "%sEnv = %s\n", name, env_str.Value() ); } // // // // // // // Standard Files // // // // // // // TODO??? // // // // // // // Misc + Exec // // // // // // // TODO? // Starter->jic->notifyJobPreSpawn( name ); // compute job's renice value by evaluating the machine's // JOB_RENICE_INCREMENT in the context of the job ad... // TODO? int nice_inc = 10; // in the below dprintfs, we want to skip past argv[0], which // is sometimes condor_exec, in the Args string. MyString args_string; args.GetArgsStringForDisplay(&args_string,1); dprintf( D_ALWAYS, "About to exec %s script: %s %s\n", name, exe_path.Value(), args_string.Value() ); // If there is a requested coresize for this job, enforce it. // It is truncated because you can't put an unsigned integer // into a classad. I could rewrite condor's use of ATTR_CORE_SIZE to // be a float, but then when that attribute is read/written to the // job queue log by/or shared between versions of Condor which view the // type of that attribute differently, calamity would arise. int core_size_truncated; size_t core_size; size_t *core_size_ptr = NULL; if ( JobAd->LookupInteger(ATTR_CORE_SIZE, core_size_truncated) ) { core_size = (size_t)core_size_truncated; core_size_ptr = &core_size; } JobPid = daemonCore->Create_Process(exe_path.Value(), args, PRIV_USER_FINAL, 1, FALSE, FALSE, &job_env, Starter->jic->jobIWD(), NULL, NULL, NULL, NULL, nice_inc, NULL, DCJOBOPT_NO_ENV_INHERIT, core_size_ptr ); //NOTE: Create_Process() saves the errno for us if it is an //"interesting" error. char const *create_process_error = NULL; int create_process_errno = errno; if( JobPid == FALSE && errno ) { create_process_error = strerror( errno ); } if( JobPid == FALSE ) { JobPid = -1; if( create_process_error ) { MyString err_msg = "Failed to execute '"; err_msg += exe_path.Value(); err_msg += "'"; if(!args_string.IsEmpty()) { err_msg += " with arguments "; err_msg += args_string.Value(); } err_msg += ": "; err_msg += create_process_error; Starter->jic->notifyStarterError( err_msg.Value(), true, CONDOR_HOLD_CODE_FailedToCreateProcess, create_process_errno ); } EXCEPT( "Create_Process(%s,%s, ...) failed", exe_path.Value(), args_string.Value() ); return 0; } dprintf( D_ALWAYS, "Create_Process succeeded, pid=%d\n", JobPid ); job_start_time.getTime(); return 1; }
int JavaProc::StartJob() { MyString java_cmd; char* jarfiles = NULL; ArgList args; MyString arg_buf; // Since we are adding to the argument list, we may need to deal // with platform-specific arg syntax in the user's args in order // to successfully merge them with the additional java VM args. args.SetArgV1SyntaxToCurrentPlatform(); // Construct the list of jar files for the command line // If a jar file is transferred locally, use its local name // (in the execute directory) // otherwise use the original name StringList jarfiles_orig_list; StringList jarfiles_local_list; StringList* jarfiles_final_list = NULL; if( JobAd->LookupString(ATTR_JAR_FILES,&jarfiles) ) { jarfiles_orig_list.initializeFromString( jarfiles ); free( jarfiles ); jarfiles = NULL; char * jarfile_name; const char * base_name; struct stat stat_buff; if( Starter->jic->iwdIsChanged() ) { // If the job's IWD has been changed (because we're // running in the sandbox due to file transfer), we // need to use a local version of the path to the jar // files, not the full paths from the submit machine. jarfiles_orig_list.rewind(); while( (jarfile_name = jarfiles_orig_list.next()) ) { // Construct the local name base_name = condor_basename( jarfile_name ); MyString local_name = execute_dir; local_name += DIR_DELIM_CHAR; local_name += base_name; if( stat(local_name.Value(), &stat_buff) == 0 ) { // Jar file exists locally, use local name jarfiles_local_list.append( local_name.Value() ); } else { // Use the original name jarfiles_local_list.append (jarfile_name); } } // while(jarfiles_orig_list) // jarfiles_local_list is our real copy... jarfiles_final_list = &jarfiles_local_list; } else { // !iwdIsChanged() // just use jarfiles_orig_list as our real copy... jarfiles_final_list = &jarfiles_orig_list; } } startfile.formatstr("%s%cjvm.start",execute_dir,DIR_DELIM_CHAR); endfile.formatstr("%s%cjvm.end",execute_dir,DIR_DELIM_CHAR); if( !java_config(java_cmd,&args,jarfiles_final_list) ) { dprintf(D_FAILURE|D_ALWAYS,"JavaProc: Java is not configured!\n"); return 0; } JobAd->Assign(ATTR_JOB_CMD, java_cmd.Value()); arg_buf.formatstr("-Dchirp.config=%s%cchirp.config",execute_dir,DIR_DELIM_CHAR); args.AppendArg(arg_buf.Value()); char *jvm_args1 = NULL; char *jvm_args2 = NULL; MyString jvm_args_error; bool jvm_args_success = true; JobAd->LookupString(ATTR_JOB_JAVA_VM_ARGS1, &jvm_args1); JobAd->LookupString(ATTR_JOB_JAVA_VM_ARGS2, &jvm_args2); if(jvm_args2) { jvm_args_success = args.AppendArgsV2Raw(jvm_args2, &jvm_args_error); } else if(jvm_args1) { jvm_args_success = args.AppendArgsV1Raw(jvm_args1, &jvm_args_error); } free(jvm_args1); free(jvm_args2); if (!jvm_args_success) { dprintf(D_ALWAYS, "JavaProc: failed to parse JVM args: %s\n", jvm_args_error.Value()); return 0; } args.AppendArg("CondorJavaWrapper"); args.AppendArg(startfile.Value()); args.AppendArg(endfile.Value()); MyString args_error; if(!args.AppendArgsFromClassAd(JobAd,&args_error)) { dprintf(D_ALWAYS,"JavaProc: failed to read job arguments: %s\n", args_error.Value()); return 0; } // We are just talking to ourselves, so it is fine to use argument // syntax compatible with this current version of Condor. CondorVersionInfo ver_info; if(!args.InsertArgsIntoClassAd(JobAd,&ver_info,&args_error)) { dprintf(D_ALWAYS,"JavaProc: failed to insert java job arguments: %s\n", args_error.Value()); return 0; } dprintf(D_ALWAYS,"JavaProc: Cmd=%s\n",java_cmd.Value()); MyString args_string; args.GetArgsStringForDisplay(&args_string); dprintf(D_ALWAYS,"JavaProc: Args=%s\n",args_string.Value()); return VanillaProc::StartJob(); }