From: denes Date: Wed, 29 Jul 2009 16:40:00 +0000 (+0000) Subject: Added TreeLimitRun X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=commitdiff_plain;h=4e51145c79bf8c5c8d42442f74b2c63ff68141ed;p=helm.git Added TreeLimitRun --- diff --git a/helm/software/components/binaries/matitaprover/TreeLimitedRun.c b/helm/software/components/binaries/matitaprover/TreeLimitedRun.c new file mode 100644 index 000000000..9579db404 --- /dev/null +++ b/helm/software/components/binaries/matitaprover/TreeLimitedRun.c @@ -0,0 +1,854 @@ +//--------------------------------------------------------------------------- +//----Program to watch CPU usage of a process +//----TreeLimitedRun +//--------------------------------------------------------------------------- +//----SUN or LINUX or OSX (OSX is very generic) +#if (!defined(SUN) && !defined(LINUX) && !defined(OSX)) + #define LINUX +#endif +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SUN +#include +#endif +//--------------------------------------------------------------------------- +#define STRING_LENGTH 80 +#define MAX_PROCESSES 1000 +#define DEFAULT_DELAY_BETWEEN_CHECKS 10 +#define NANOSECONDS 1E9 +#define MICROSECONDS 1E6 +#define JIFFIES 100 + +#define STDOUT 1 +#define STDERR 2 + +typedef char String[STRING_LENGTH]; + +typedef struct { + int Active; + pid_t PID; + pid_t PPID; + double CPUTime; + double AccumulatedCPUTime; +} ProcessData; + +typedef ProcessData ProcessDataArray[MAX_PROCESSES]; + +int GlobalInterrupted; +int GlobalSignalReceived; +//--------------------------------------------------------------------------- +void SIGCHLDHandler(int TheSignal) { + +//DEBUG printf("Some child has died\n"); +//----The child is reaped in WatchChildTree + +} +//--------------------------------------------------------------------------- +void SIGCHLDReaper(int TheSignal) { + + int DeadPID; + int Status; + + while ((DeadPID = waitpid(-1,&Status,WNOHANG)) > 0) { +//DEBUG printf("!!! Child %d of TreeLimitedRun %d has died\n",DeadPID,getpid());fflush(stdout); + } + +} +//--------------------------------------------------------------------------- +//----Controllers in the CASC/SystemOnTPTP/SSCPA/etc hierarchy may send +//----SIGQUIT to stop things +void SIGQUITHandler(int TheSignal) { + +//DEBUG printf("!!! TreeLimitedRun %d got a signal %d\n",getpid(),TheSignal);fflush(stdout); + GlobalInterrupted = 1; + GlobalSignalReceived = TheSignal; + +} +//--------------------------------------------------------------------------- +void SetCPUTimeLimit(rlim_t CPUTimeLimit) { + + struct rlimit ResourceLimits; + +//----Set the signal handler +//----No point - signals are reset on exec +//----For some reason this is still needed, or the signal doesn't work + if (signal(SIGXCPU,SIGQUITHandler) == SIG_ERR) { + perror("Setting signal handler"); + exit(EXIT_FAILURE); + } + +//----Limit the CPU time. Need to get old one for hard limit field + if (getrlimit(RLIMIT_CPU,&ResourceLimits) == -1) { + perror("Getting CPU limit"); + exit(EXIT_FAILURE); + } +//----Set new CPU limit in ms (sent in secs) + ResourceLimits.rlim_cur = CPUTimeLimit; + if (setrlimit(RLIMIT_CPU,&ResourceLimits) == -1) { + perror("Setting CPU limit"); + exit(EXIT_FAILURE); + } +} +//----------------------------------------------------------------------------- +void SetMemoryLimit(rlim_t MemoryLimit) { + + struct rlimit ResourceLimits; + +#ifdef RLIMIT_AS +#define THE_LIMIT RLIMIT_AS +#else +#define THE_LIMIT RLIMIT_DATA +#endif + +//----Limit the memory. Need to get old one for hard limit field + if (getrlimit(THE_LIMIT,&ResourceLimits) == -1) { + perror("Getting memory limit"); + exit(EXIT_FAILURE); + } +//----Set new memory limit + ResourceLimits.rlim_max = MemoryLimit; + ResourceLimits.rlim_cur = MemoryLimit; + if (setrlimit(THE_LIMIT,&ResourceLimits) == -1) { + perror("Setting memory limit"); + exit(EXIT_FAILURE); + } +} +//--------------------------------------------------------------------------- +//----Prevent core dumps that occur on timeout +void SetNoCoreDump(void) { + + struct rlimit ResourceLimits; + +//----Get old resource limits + if (getrlimit(RLIMIT_CORE,&ResourceLimits) == -1) { + perror("Getting resource limit:"); + exit(EXIT_FAILURE); + } +//----Set new core limit to 0 + ResourceLimits.rlim_cur = 0; + if (setrlimit(RLIMIT_CORE,&ResourceLimits) == -1) { + perror("Setting resource limit:"); + exit(EXIT_FAILURE); + } +} +//--------------------------------------------------------------------------- +#ifdef LINUX +void GetProcessesOwnedByMe(uid_t MyRealUID,ProcessDataArray OwnedPIDs, +int *NumberOfOwnedPIDs) { + + DIR *ProcDir; + struct dirent *ProcessDir; + pid_t UID,PID,PPID; + FILE *ProcFile; + String ProcFileName,Line; + + if ((ProcDir = opendir("/proc")) == NULL) { + perror("ERROR: Cannot opendir /proc\n"); + exit(EXIT_FAILURE); + } +//DEBUG printf("look for processes owned by %d\n",MyRealUID); + + *NumberOfOwnedPIDs = 0; + while ((ProcessDir = readdir(ProcDir)) != NULL) { + if (isdigit(ProcessDir->d_name[0])) { + PID = (pid_t)atoi(ProcessDir->d_name); + sprintf(ProcFileName,"/proc/%d/status",PID); + if ((ProcFile = fopen(ProcFileName,"r")) != NULL) { + PPID = -1; + UID = -1; + while ((PPID == -1 || UID == -1) && +fgets(Line,STRING_LENGTH,ProcFile) != NULL) { + sscanf(Line,"PPid: %d",&PPID); + sscanf(Line,"Uid: %d",&UID); + } + fclose(ProcFile); +//----Check that data was found +//DEBUG printf("PID = %d PPID = %d UID = %d\n",PID,PPID,UID); + if (PPID == -1 || UID == -1) { + fprintf(stderr,"Could not get process information\n"); + exit(EXIT_FAILURE); + } +//----Check if this process is owned by this user + if (UID == MyRealUID) { +//----Record the PIDs as potentially relevant + OwnedPIDs[*NumberOfOwnedPIDs].Active = 1; + OwnedPIDs[*NumberOfOwnedPIDs].PID = PID; + OwnedPIDs[*NumberOfOwnedPIDs].PPID = PPID; + (*NumberOfOwnedPIDs)++; +//DEBUG printf("%d I own PID = %d PPID = %d UID = %d\n",*NumberOfOwnedPIDs,PID,PPID,UID); + if (*NumberOfOwnedPIDs >= MAX_PROCESSES) { + fprintf(stderr,"ERROR: Out of save process space\n"); + exit(EXIT_FAILURE); + } + } + } else { +//----Bloody child just died + } + } + } + closedir(ProcDir); +} +//--------------------------------------------------------------------------- +float GetProcessTime(pid_t PID,int IncludeSelf,int IncludeChildren) { + + FILE *ProcFile; + String ProcFileName; + float MyTime,ChildTime,ProcessTime; + int UserModeJiffies,SystemModeJiffies,ChildUserModeJiffies, +ChildSystemModeJiffies; + + ProcessTime = 0; + sprintf(ProcFileName,"/proc/%d/stat",PID); + if ((ProcFile = fopen(ProcFileName,"r")) != NULL) { + fscanf(ProcFile,"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %d %d %d %d",&UserModeJiffies,&SystemModeJiffies,&ChildUserModeJiffies, +&ChildSystemModeJiffies); + fclose(ProcFile); +//DEBUG printf("%d: my jiffies = %d, dead child jiffies = %d\n",PID,UserModeJiffies+SystemModeJiffies,ChildUserModeJiffies+ChildSystemModeJiffies); +//----Time used by this process + MyTime = ((float)(UserModeJiffies + SystemModeJiffies))/JIFFIES; +//----Time used by this process's dead children (man pages are wrong - does +//----not include my jiffies) + ChildTime = ((float)(ChildUserModeJiffies + ChildSystemModeJiffies))/ +JIFFIES; + if (IncludeSelf) { + ProcessTime += MyTime; + } + if (IncludeChildren) { + ProcessTime += ChildTime; + } +//DEBUG printf("Process time for %d is %f\n",PID,ProcessTime); + return(ProcessTime); + } else { +//----Bloody process died, return 0 and catch it in the parent next time + return(0); + } +} +#endif +//--------------------------------------------------------------------------- +#ifdef SUN +void GetProcessesOwnedByMe(uid_t MyRealUID,ProcessDataArray OwnedPIDs, +int *NumberOfOwnedPIDs) { + + DIR *ProcDir; + struct dirent *ProcessDir; + pid_t PID; + struct psinfo ProcessRecord; + FILE *ProcFile; + String ProcFileName; + + if ((ProcDir = opendir("/proc")) == NULL) { + perror("ERROR: Cannot opendir /proc\n"); + exit(EXIT_FAILURE); + } + +//DEBUG printf("look for processes owned by %d\n",MyRealUID); + + *NumberOfOwnedPIDs = 0; + while ((ProcessDir = readdir(ProcDir)) != NULL) { + if (isdigit((int)ProcessDir->d_name[0])) { + PID = (pid_t)atoi(ProcessDir->d_name); + sprintf(ProcFileName,"/proc/%d/psinfo",(int)PID); + if ((ProcFile = fopen(ProcFileName,"r")) != NULL) { + fread(&ProcessRecord,sizeof(ProcessRecord),1,ProcFile); + fclose(ProcFile); +//----Check if this process is owned by this user + if (ProcessRecord.pr_uid == MyRealUID) { +//----Record the PIDs as potentially relevant + OwnedPIDs[*NumberOfOwnedPIDs].PID = PID; + OwnedPIDs[*NumberOfOwnedPIDs].PPID = ProcessRecord.pr_ppid; + (*NumberOfOwnedPIDs)++; + if (*NumberOfOwnedPIDs >= MAX_PROCESSES) { + fprintf(stderr,"ERROR: Out of save process space\n"); + exit(EXIT_FAILURE); + } + } + } else { +//----Bloody child just died + } + } + } + closedir(ProcDir); +} +//--------------------------------------------------------------------------- +float GetProcessTime(pid_t PID,int IncludeSelf,int IncludeChildren) { + + FILE *ProcFile; + String ProcFileName; + pstatus_t StatusRecord; + float ProcessTime; + + ProcessTime = 0; + sprintf(ProcFileName,"/proc/%d/status",(int)PID); + if ((ProcFile = fopen(ProcFileName,"r")) != NULL) { + fread(&StatusRecord,sizeof(StatusRecord),1,ProcFile); + fclose(ProcFile); + if (IncludeSelf) { + ProcessTime += StatusRecord.pr_utime.tv_sec + +StatusRecord.pr_stime.tv_sec + +((float)(StatusRecord.pr_utime.tv_nsec+StatusRecord.pr_stime.tv_nsec))/ +NANOSECONDS; + } + if (IncludeChildren) { + ProcessTime += StatusRecord.pr_cutime.tv_sec + +StatusRecord.pr_cstime.tv_sec + +((float)(StatusRecord.pr_cutime.tv_nsec+StatusRecord.pr_cstime.tv_nsec))/ +NANOSECONDS; + } +//DEBUG printf("Process %d has used U %ld +n%ld + S %ld +n%ld + CU %ld +n%ld + CS %ld +n%ld = %.1f\n", +//DEBUG PID,StatusRecord.pr_utime.tv_sec,StatusRecord.pr_utime.tv_nsec, +//DEBUG StatusRecord.pr_stime.tv_sec,StatusRecord.pr_stime.tv_nsec, +//DEBUG StatusRecord.pr_cutime.tv_sec,StatusRecord.pr_cutime.tv_nsec, +//DEBUG StatusRecord.pr_cstime.tv_sec,StatusRecord.pr_cstime.tv_nsec, +//DEBUG ProcessTime); + return(ProcessTime); + } else { +//----Bloody child died, return 0 and catch it in the parent next time + return(0); + } +} +#endif //----SUN +//--------------------------------------------------------------------------- +#ifdef OSX +//----No looking in /proc for OSX +#endif +//--------------------------------------------------------------------------- +int PIDInArray(pid_t PID,ProcessDataArray PIDs,int NumberOfPIDs) { + + int PIDIndex; + + for (PIDIndex = 0;PIDIndex < NumberOfPIDs;PIDIndex++) { + if (PIDs[PIDIndex].PID == PID) { + return(1); + } + } + return(0); +} +//--------------------------------------------------------------------------- +#if (defined(LINUX)||defined(SUN)) +//----Only for systems that have /proc + +int GetTreeTimes(uid_t MyRealUID,pid_t FirstBornPID,ProcessDataArray +TreeTimes) { + + ProcessDataArray OwnedPIDs; + int NumberOfOwnedPIDs; + int NumberOfTreeTimes; + int CurrentTreeIndex; + int OwnedIndex; + +//----Get the list of processes owned by this user + GetProcessesOwnedByMe(MyRealUID,OwnedPIDs,&NumberOfOwnedPIDs); + +//----Check that the root of the tree is still there +//DEBUG printf("Check if %d is alive\n",FirstBornPID); + if (!PIDInArray(FirstBornPID,OwnedPIDs,NumberOfOwnedPIDs)) { +//DEBUG printf("It is dead\n"); + return(0); + } +//DEBUG printf("It is alive\n"); + +//----Find those in the process tree, and get their times + CurrentTreeIndex = 0; + TreeTimes[0].Active = 1; + TreeTimes[0].PID = FirstBornPID; + TreeTimes[0].PPID = MyRealUID; + TreeTimes[0].CPUTime = GetProcessTime(TreeTimes[0].PID,1,1); + NumberOfTreeTimes = 1; + + while (CurrentTreeIndex < NumberOfTreeTimes) { +//DEBUG printf("%d %d is in the tree\n",TreeTimes[CurrentTreeIndex].PID,TreeTimes[CurrentTreeIndex].PPID); +//----Scan for offspring + TreeTimes[CurrentTreeIndex].CPUTime = +GetProcessTime(TreeTimes[CurrentTreeIndex].PID,1,1); + for (OwnedIndex = 0; OwnedIndex < NumberOfOwnedPIDs; OwnedIndex++) { + if (OwnedPIDs[OwnedIndex].PPID == TreeTimes[CurrentTreeIndex].PID) { + TreeTimes[NumberOfTreeTimes].Active = 1; + TreeTimes[NumberOfTreeTimes].PID = OwnedPIDs[OwnedIndex].PID; + TreeTimes[NumberOfTreeTimes].PPID = OwnedPIDs[OwnedIndex].PPID; + NumberOfTreeTimes++; + } + } +//----Move on to the next process in the tree + CurrentTreeIndex++; + } + + return(NumberOfTreeTimes); +} + +#endif +#ifdef OSX +//----No /proc for OSX +#endif +//--------------------------------------------------------------------------- +//----Send signals and reports if process is known to be gone +int SignalAndReport(int PID,int Signal,int RepeatUntilTerminated, +char * ProcessType) { + + String ErrorMessage; + extern int errno; + int Terminated; + int NumberOfLoops; + + Terminated = 0; + NumberOfLoops = 0; + do { + NumberOfLoops++; +//DEBUG printf("!!! TreeLimitedRun %d sends signal %d to %s %d\n",getpid(),Signal,ProcessType,PID);fflush(stdout); + if (kill(PID,Signal) != 0) { +//DEBUG printf("The kill errno is %d\n",errno); +//----If process no longer exists record that to avoid killing again + if (errno == ESRCH) { + Terminated = 1; + } else { + sprintf(ErrorMessage, +"!!! ERROR: TreeLimitedRun %d cannot signal %s %d with %d",getpid(),ProcessType, +PID,Signal); + perror(ErrorMessage); + } + } +//----Must do perror after errno, as perror clears errno + } while (RepeatUntilTerminated && !Terminated && NumberOfLoops < 10); + + return(Terminated); +} +//--------------------------------------------------------------------------- +void ChildKillTree(int TargetIndex,ProcessDataArray TreeTimes, +int NumberInTree,int Signal) { + + int ChildIndex; + +//DEBUG printf("!!! TreeLimitedRun %d killing tree below PID %d with %d\n",getpid(),TreeTimes[TargetIndex].PID,Signal);fflush(stdout); + for (ChildIndex=0; ChildIndex < NumberInTree; ChildIndex++) { + if (TreeTimes[TargetIndex].PID == TreeTimes[ChildIndex].PPID) { + ChildKillTree(ChildIndex,TreeTimes,NumberInTree,Signal); + } +//TOO SLOW? usleep(100000); + } + if (TreeTimes[TargetIndex].Active) { + if (SignalAndReport(TreeTimes[TargetIndex].PID,Signal, +Signal == SIGKILL,"tree process")) { + TreeTimes[TargetIndex].Active = 0; + } + } +} +//--------------------------------------------------------------------------- +int KillTree(uid_t MyRealUID,pid_t FirstBornPID,int Signal) { + + int NumberOfTreeTimes; + extern int errno; + +#if (defined(LINUX)||defined(SUN)) + ProcessDataArray TreeTimes; + + if ((NumberOfTreeTimes = GetTreeTimes(MyRealUID,FirstBornPID,TreeTimes)) > +0) { + +//----The first born gets it first so that it can curb its descendants nicely + if (TreeTimes[0].Active) { +//DEBUG printf("!!! TreeLimitedRun %d killing top process %d with %d\n",getpid(),TreeTimes[0].PID,Signal);fflush(stdout); +//----TreeTimes[0].PID is FirstBornPID + if (SignalAndReport(TreeTimes[0].PID,Signal,Signal == SIGKILL, +"top process")) { + TreeTimes[0].Active = 0; + } + } + +//----200000 is not enough - EP's eproof script gets killed before it can +//----kill eprover + usleep(500000); +//----Now gently from the bottom up + ChildKillTree(0,TreeTimes,NumberOfTreeTimes,Signal); + usleep(100000); +//----Now viciously from the bottom up + ChildKillTree(0,TreeTimes,NumberOfTreeTimes,SIGKILL); + } +#endif +#ifdef OSX + int Active; + + Active = 1; +//----The first born gets it first so that it can curb its descendants nicely + if (SignalAndReport(FirstBornPID,Signal,Signal == SIGKILL,"top process")) { + Active = 0; + } + if (Active) { + usleep(100000); +//----Now viciously + SignalAndReport(FirstBornPID,SIGKILL,1,"only process"); + } + NumberOfTreeTimes = 1; +#endif + + return(NumberOfTreeTimes); +} +//--------------------------------------------------------------------------- +void KillOrphans(uid_t MyRealUID,ProcessDataArray SavePIDs, +int NumberOfSavePIDs) { + +#if (defined(LINUX)||defined(SUN)) + + ProcessDataArray OwnedPIDs; + int NumberOfOwnedPIDs; + int OwnedIndex; + int NumberOfOrphansKilled; + extern int errno; + + do { +//----Get the list of processes owned by this user + GetProcessesOwnedByMe(MyRealUID,OwnedPIDs,&NumberOfOwnedPIDs); + + NumberOfOrphansKilled = 0; + for (OwnedIndex = 0; OwnedIndex < NumberOfOwnedPIDs; OwnedIndex++) { +//DEBUG printf("!!! TreeLimitedRun %d considers %d with parent %d\n",getpid(),OwnedPIDs[OwnedIndex].PID, OwnedPIDs[OwnedIndex].PPID);fflush(stdout); + if (OwnedPIDs[OwnedIndex].PPID == 1 && +!PIDInArray(OwnedPIDs[OwnedIndex].PID,SavePIDs,NumberOfSavePIDs)) { +//DEBUG printf("!!! TreeLimitedRun %d kills orphan %d\n",getpid(),OwnedPIDs[OwnedIndex].PID);fflush(stdout); + if (SignalAndReport(OwnedPIDs[OwnedIndex].PID,SIGQUIT,0, +"orphan")) { + OwnedPIDs[OwnedIndex].Active = 0; + } + if (OwnedPIDs[OwnedIndex].Active) { + sleep(1); + SignalAndReport(OwnedPIDs[OwnedIndex].PID,SIGKILL,1, +"orphan"); + } + NumberOfOrphansKilled++; + } + } + if (NumberOfOrphansKilled > 0) { + printf("Killed %d orphans\n",NumberOfOrphansKilled); + } + } while (NumberOfOrphansKilled > 0); + +#endif +#ifdef OSX +//----No orphans known for OSX +#endif +} +//--------------------------------------------------------------------------- +void PrintTimes(char* Tag,float TreeCPUTime,float WCTime) { + +//----You can print times with more accuracy here + printf("%s: %.1f CPU %.1f WC\n",Tag,TreeCPUTime,WCTime); + fflush(NULL); +} +//--------------------------------------------------------------------------- +float WallClockSoFar(struct timeval WCStartTime) { + + struct timeval WCEndTime; + + gettimeofday(&WCEndTime,NULL); +//DEBUG printf("Started at %ld +%f and ended at %ld +%f\n", +//DEBUG WCStartTime.tv_sec,WCStartTime.tv_usec/MICROSECONDS, +//DEBUG WCEndTime.tv_sec,WCEndTime.tv_usec/MICROSECONDS); + + return((WCEndTime.tv_sec - WCStartTime.tv_sec) + +(WCEndTime.tv_usec - WCStartTime.tv_usec)/MICROSECONDS); + +} +//--------------------------------------------------------------------------- +double AccumulateTreeTime(int TargetIndex,ProcessDataArray TreeTimes, +int NumberInTree) { + + int ChildIndex; + + TreeTimes[TargetIndex].AccumulatedCPUTime = TreeTimes[TargetIndex].CPUTime; + for (ChildIndex=0; ChildIndex < NumberInTree; ChildIndex++) { + if (TreeTimes[TargetIndex].PID == TreeTimes[ChildIndex].PPID) { + TreeTimes[TargetIndex].AccumulatedCPUTime += +AccumulateTreeTime(ChildIndex,TreeTimes,NumberInTree); + } + } + + return(TreeTimes[TargetIndex].AccumulatedCPUTime); +} +//--------------------------------------------------------------------------- +float WatchChildTree(int MyPID,int ChildPID,int CPUTimeLimit, +int DelayBetweenChecks,struct timeval WCStartTime,int PrintEachCheck) { + + double TreeTime,LastTreeTime,LostTime; + int NumberInTree; + int KilledInTree; + int Status; + int DeadPID; +#if (defined(LINUX)||defined(SUN)) + ProcessDataArray TreeTimes; +#endif +#ifdef OSX + struct rusage ResourceUsage; +#endif + + LastTreeTime = 0.0; + LostTime = 0.0; + +//----Loop watching times taken. Order is important - get time before +//----checking for interrupt + do { +#if (defined(LINUX)||defined(SUN)) +//----Look at the tree + NumberInTree = GetTreeTimes(getuid(),ChildPID,TreeTimes); + TreeTime = AccumulateTreeTime(0,TreeTimes,NumberInTree); +//DEBUG fprintf(stderr,"now %5.2f limit %d\n",TreeTime,CPUTimeLimit); +//----For those with /proc, reap the children. Need to reap late so /proc +//----entries do not disappear + while ((DeadPID = waitpid(-1,&Status,WNOHANG)) > 0) { + NumberInTree--; +//DEBUG fprintf(stderr,"The child %d has died\n",DeadPID); + } +#endif +#ifdef OSX +//----Check if child is gone (-1 if no child, 0 if not dead, PID if dead) + DeadPID = waitpid(-1,&Status,WNOHANG); + if (DeadPID == ChildPID || DeadPID == -1) { + TreeTime = LastTreeTime; + NumberInTree = 0; + } else { +//----Maybe more than 1, but we don't know in OSX version + NumberInTree = 1; + } + if (getrusage(RUSAGE_CHILDREN,&ResourceUsage) != -1) { + TreeTime = ResourceUsage.ru_utime.tv_sec + +ResourceUsage.ru_utime.tv_usec / 1000000 + ResourceUsage.ru_stime.tv_sec + +ResourceUsage.ru_stime.tv_usec / 1000000; + } else { + printf("TreeLimitedRun could not getrusage\n"); + TreeTime = LastTreeTime; + } +#endif + +//DEBUG fprintf(stderr,"acc time is %.2f\n",TreeTime); + if (TreeTime < LastTreeTime) { + LostTime += LastTreeTime - TreeTime; + printf("WARNING: TreeLimitedRun lost %.2fs, total lost is %.2fs\n", +LastTreeTime - TreeTime,LostTime); + } +//DEBUG printf("lost time is %.2f\n",LostTime); + LastTreeTime = TreeTime; + TreeTime += LostTime; + +//----Print each loop if requested + if (PrintEachCheck) { + PrintTimes("WATCH",TreeTime,WallClockSoFar(WCStartTime)); + } +//----If we're going to loop, wait a bit first +//----DANGER - if the last descedantprocess dies between GetTreeTimes() and +//----here, it still waits. + if ((CPUTimeLimit == 0 || TreeTime <= CPUTimeLimit) && +NumberInTree > 0 && !GlobalInterrupted) { + sleep(DelayBetweenChecks); + } + } while ((CPUTimeLimit == 0 || TreeTime <= CPUTimeLimit) && +NumberInTree > 0 && !GlobalInterrupted); + +//----From now on reap normally + if (signal(SIGCHLD,SIGCHLDReaper) == SIG_ERR) { + perror("ERROR: Could not set SIGCHLD handler"); + exit(EXIT_FAILURE); + } +//----Reap anyway in case I missed some + SIGCHLDReaper(0); + +//----If over time limit, stop them all (XCPU to top guy first) + if (NumberInTree > 0 && TreeTime > CPUTimeLimit) { + KilledInTree = KillTree(getuid(),ChildPID,SIGXCPU); +//DEBUG printf("Killed %d in tree\n",KilledInTree); + } + +//----If global interrupted, then send it on + if (NumberInTree > 0 && GlobalInterrupted) { + KilledInTree = KillTree(getuid(),ChildPID,GlobalSignalReceived); +//DEBUG printf("Killed %d in tree\n",KilledInTree); + } + + return(TreeTime); +} +//--------------------------------------------------------------------------- +int main(int argc,char *argv[]) { + + int CPUTimeLimit; + int WCTimeLimit; + int MemoryLimit; + int ArgNumber; + int QuietnessLevel; + int ArgOffset; + pid_t ChildPID; + float TreeCPUTime; + float WCTime; + struct timeval WCStartTime; + int DelayBetweenChecks; + int PrintEachCheck = 0; + ProcessDataArray SavePIDs; + int NumberOfSavePIDs; + int Status; + +//----Check the quietness level + if (argc >= 2 && strstr(argv[1],"-q") == argv[1]) { + ArgOffset = 1; + QuietnessLevel = atoi(&argv[ArgOffset][2]); + } else { + QuietnessLevel = 1; + ArgOffset = 0; + } + +//----Look for time and print flags + if (argc >= ArgOffset+2 && +strstr(argv[ArgOffset+1],"-t") == argv[ArgOffset+1]) { + ArgOffset++; + DelayBetweenChecks = atoi(&argv[ArgOffset][2]); + } else { + if (argc >= ArgOffset+2 && +strstr(argv[ArgOffset+1],"-p") == argv[ArgOffset+1]) { + PrintEachCheck = 1; + ArgOffset++; + DelayBetweenChecks = atoi(&argv[ArgOffset][2]); + } else { + DelayBetweenChecks = DEFAULT_DELAY_BETWEEN_CHECKS; + } + } + + if (argc - ArgOffset >= 4) { +//----Redirect stderr to stdout + if (dup2(STDOUT,STDERR) == -1) { + perror("ERROR: Cannot dup STDERR to STDOUT"); + } + +//----Extract time limits + CPUTimeLimit = atoi(argv[ArgOffset+1]); + WCTimeLimit = atoi(argv[ArgOffset+2]); + if (isdigit((int)argv[ArgOffset+3][0])) { + MemoryLimit = atoi(argv[ArgOffset+3]); + ArgOffset++; + } else { + MemoryLimit = 0; + } + + if (QuietnessLevel == 0) { + printf( +"TreeLimitedRun: ----------------------------------------------------------\n"); + printf("TreeLimitedRun: %s ",argv[ArgOffset+3]); + for (ArgNumber=ArgOffset+4;ArgNumber 0) { + printf("TreeLimitedRun: Memory limit is %dbytes\n", +MemoryLimit); + } +//----Output the PID for possible later use + printf("TreeLimitedRun: PID is %d\n",(int)getpid()); + printf( +"TreeLimitedRun: ----------------------------------------------------------\n"); + fflush(stdout); + } + SetNoCoreDump(); + +//----Set handler for when child dies + if (signal(SIGCHLD,SIGCHLDHandler) == SIG_ERR) { + perror("ERROR: Could not set SIGCHLD handler"); + exit(EXIT_FAILURE); + } +//----Set handler for global interruptions and alarms + GlobalInterrupted = 0; + GlobalSignalReceived = 0; + if (signal(SIGQUIT,SIGQUITHandler) == SIG_ERR) { + perror("ERROR: Could not set SIGQUIT handler"); + exit(EXIT_FAILURE); + } + if (signal(SIGALRM,SIGQUITHandler) == SIG_ERR) { + perror("ERROR: Could not set SIGALRM handler"); + exit(EXIT_FAILURE); + } + +#if (defined(LINUX)||defined(SUN)) +//----Record running processes at start (xeyes, gnome, etc) + GetProcessesOwnedByMe(getuid(),SavePIDs,&NumberOfSavePIDs); +#endif +#ifdef OSX +//----No recording processes for OSX +#endif + +//----Fork for ATP process + if ((ChildPID = fork()) == -1) { + perror("ERROR: Cannot fork for ATP system process"); + exit(EXIT_FAILURE); + } + +//----In child, set limits and execute the ATP system + if (ChildPID == 0) { + if (setvbuf(stdout,NULL,_IONBF,0) != 0) { + perror("Setting unbuffered"); + } +//DEBUG printf("The prover PID will be %d\n",getpid()); +//----Set memory limit for child only + if (MemoryLimit > 0) { + SetMemoryLimit(MemoryLimit); + } + +#if (defined(LINUX)||defined(SUN)) +//----Systems with /proc are stopped by this program with kill +#endif +#ifdef OSX +//----In OSX case, child must limit itself + if (CPUTimeLimit > 0) { + SetCPUTimeLimit(CPUTimeLimit); + } +#endif + + execvp(argv[ArgOffset+3],argv+ArgOffset+3); + perror("Cannot exec"); + exit(EXIT_FAILURE); + +//----In parent, set limits and watch the ATP system + } else { + if (WCTimeLimit > 0) { + alarm(WCTimeLimit); + } +//----Record start time + gettimeofday(&WCStartTime,NULL); + TreeCPUTime = 0; + WCTime = 0; + +//----Watch the tree of processes + TreeCPUTime = WatchChildTree(getpid(),ChildPID,CPUTimeLimit, +DelayBetweenChecks,WCStartTime,PrintEachCheck); + +//----Record end WC time + WCTime = WallClockSoFar(WCStartTime); + +//----See if the time is increased by looking at my children +//----Not sure what this was for +// ChildTime = GetProcessTime(getpid(),0,1); +// if (ChildTime > TreeCPUTime) { +// TreeCPUTime = ChildTime; +// } + + PrintTimes("FINAL WATCH",TreeCPUTime,WCTime); + +//----Sweep for orphans + KillOrphans(getuid(),SavePIDs,NumberOfSavePIDs); +//----Reap any remaining + while (wait(&Status) != -1) { + sleep(1); +//DEBUG printf("!!! Waiting for children that havn't died\n"); + } + } + } else { + printf("Usage: %s [-q] [-t|-p] [] \n", +argv[0]); + } + + return(0); +} +//--------------------------------------------------------------------------- diff --git a/helm/software/components/binaries/matitaprover/run_on_a_list.sh b/helm/software/components/binaries/matitaprover/run_on_a_list.sh index c80e128e2..420b6b956 100755 --- a/helm/software/components/binaries/matitaprover/run_on_a_list.sh +++ b/helm/software/components/binaries/matitaprover/run_on_a_list.sh @@ -4,11 +4,11 @@ if [ -z "$1" ] || [ -z "$2" ]; then echo usage: $0 timeout problem_list exit 1 fi - +gcc TreeLimitedRun.c -o TreeLimitedRun > log for PROBLEM in `cat $2`; do echo running on $PROBLEM - ./matitaprover.native --timeout $1 --tptppath ~/TPTP-v3.7.0/ $PROBLEM \ + ./TreeLimitedRun -q0 $1 $(($1*2)) ./matitaprover.native --tptppath ~/TPTP-v3.7.0/ $PROBLEM \ >> log 2>&1 echo So far `grep 'SZS status Unsatisfiable' log|wc -l` solved done