def run(self): # Calculate how often disk should be checked if ostype == "WindowsCE": disk_interval = int(repy_constants.RESOURCE_POLLING_FREQ_WINCE / repy_constants.CPU_POLLING_FREQ_WINCE) else: disk_interval = int(repy_constants.RESOURCE_POLLING_FREQ_WIN / repy_constants.CPU_POLLING_FREQ_WIN) current_interval = 0 # What cycle are we on # Elevate our priority, above normal is higher than the usercode, and is enough for disk/mem windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # need my pid to get a process handle... mypid = os.getpid() # run forever (only exit if an error occurs) while True: try: # Check memory use, get the WorkingSetSize or RSS memused = windows_api.process_memory_info(mypid)['WorkingSetSize'] if memused > nanny_resource_limits.resource_limit("memory"): # We will be killed by the other thread... raise Exception, "Memory use '"+str(memused)+"' over limit '"+str(nanny_resource_limits.resource_limit("memory"))+"'" # Increment the interval we are on current_interval += 1 # Check if we should check the disk if (current_interval % disk_interval) == 0: # Check diskused diskused = compute_disk_use(repy_constants.REPY_CURRENT_DIR) if diskused > nanny_resource_limits.resource_limit("diskused"): raise Exception, "Disk use '"+str(diskused)+"' over limit '"+str(nanny_resource_limits.resource_limit("diskused"))+"'" if ostype == 'WindowsCE': time.sleep(repy_constants.CPU_POLLING_FREQ_WINCE) else: time.sleep(repy_constants.CPU_POLLING_FREQ_WIN) except windows_api.DeadProcess: # Process may be dead, or die while checking memory use # In any case, there is no reason to continue running, just exit harshexit.harshexit(99) except: tracebackrepy.handle_exception() print >> sys.stderr, "Nanny died! Trying to kill everything else" harshexit.harshexit(20)
def run(self): # Elevate our priority, set us to the highest so that we can more effectively throttle success = windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_HIGHEST) # If we failed to get HIGHEST priority, try above normal, else we're still at default if not success: windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # Run while the process is running while True: try: # Get the frequency frequency = repy_constants.CPU_POLLING_FREQ_WIN # Base amount of sleeping on return value of # win_check_cpu_use to prevent under/over sleeping slept = win_check_cpu_use(nanny_resource_limits.resource_limit("cpu"), self.pid) if slept == -1: # Something went wrong, try again pass elif (slept < frequency): time.sleep(frequency-slept) except windows_api.DeadProcess: # Process may be dead harshexit.harshexit(97) except: tracebackrepy.handle_exception() print >> sys.stderr, "CPU Nanny died! Trying to kill everything else" harshexit.harshexit(25)
def monitor_cpu_disk_and_mem(): if ostype == 'Linux' or ostype == 'Darwin': # Startup a CPU monitoring thread/process do_forked_resource_monitor() elif ostype == 'Windows' or ostype == 'WindowsCE': # Now we set up a cpu nanny... # Use an external CPU monitor for WinCE if ostype == 'WindowsCE': nannypath = "\"" + repy_constants.PATH_SEATTLE_INSTALL + 'win_cpu_nanny.py' + "\"" cmdline = str(os.getpid())+" "+str(nanny_resource_limits.resource_limit("cpu"))+" "+str(repy_constants.CPU_POLLING_FREQ_WINCE) windows_api.launch_python_script(nannypath, cmdline) else: WinCPUNannyThread().start() # Launch mem./disk resource nanny WindowsNannyThread().start() # Start the nmstatusinterface. Windows means repy isn't run in an external # process, so pass None instead of a process id. nmstatusinterface.launch(None) else: raise UnsupportedSystemException, "Unsupported system type: '"+osrealtype+"' (alias: "+ostype+")"
def resource_monitor(childpid, pipe_handle): """ <Purpose> Function runs in a loop forever, checking resource usage and throttling CPU. Checks CPU, memory, and disk. <Arguments> childpid: The child pid, e.g. the pid of repy pipe_handle: A handle to the pipe to the repy process. Allows sending resource use information. """ # Get our pid ourpid = os.getpid() # Calculate how often disk should be checked disk_interval = int(repy_constants.RESOURCE_POLLING_FREQ_LINUX / repy_constants.CPU_POLLING_FREQ_LINUX) current_interval = -1 # What cycle are we on # Store time of the last interval last_time = getruntime() last_CPU_time = 0 resume_time = 0 # Run forever... while True: ########### Check CPU ########### # Get elasped time currenttime = getruntime() elapsedtime1 = currenttime - last_time # Calculate against last run elapsedtime2 = currenttime - resume_time # Calculate since we last resumed repy elapsedtime = min(elapsedtime1, elapsedtime2) # Take the minimum interval last_time = currenttime # Save the current time # Safety check, prevent ZeroDivisionError if elapsedtime == 0.0: continue # Get the total cpu at this point totalCPU = os_api.get_process_cpu_time(ourpid) # Our own usage totalCPU += os_api.get_process_cpu_time(childpid) # Repy's usage # Calculate percentage of CPU used percentused = (totalCPU - last_CPU_time) / elapsedtime # Do not throttle for the first interval, wrap around # Store the totalCPU for the next cycle if last_CPU_time == 0: last_CPU_time = totalCPU continue else: last_CPU_time = totalCPU # Calculate stop time stoptime = nanny_resource_limits.calculate_cpu_sleep_interval(nanny_resource_limits.resource_limit("cpu"), percentused, elapsedtime) # If we are supposed to stop repy, then suspend, sleep and resume if stoptime > 0.0: # They must be punished by stopping os.kill(childpid, signal.SIGSTOP) # Sleep until time to resume time.sleep(stoptime) # And now they can start back up! os.kill(childpid, signal.SIGCONT) # Save the resume time resume_time = getruntime() # Send this information as a tuple containing the time repy was stopped and # for how long it was stopped write_message_to_pipe(pipe_handle, "repystopped", (currenttime, stoptime)) ########### End Check CPU ########### # ########### Check Memory ########### # Get how much memory repy is using memused = os_api.get_process_rss() # Check if it is using too much memory if memused > nanny_resource_limits.resource_limit("memory"): raise ResourceException, "Memory use '"+str(memused)+"' over limit '"+str(nanny_resource_limits.resource_limit("memory"))+"'." ########### End Check Memory ########### # ########### Check Disk Usage ########### # Increment our current cycle current_interval += 1; # Check if it is time to check the disk usage if (current_interval % disk_interval) == 0: # Reset the interval current_interval = 0 # Calculate disk used diskused = compute_disk_use(repy_constants.REPY_CURRENT_DIR) # Raise exception if we are over limit if diskused > nanny_resource_limits.resource_limit("diskused"): raise ResourceException, "Disk use '"+str(diskused)+"' over limit '"+str(nanny_resource_limits.resource_limit("diskused"))+"'." # Send the disk usage information, raw bytes used write_message_to_pipe(pipe_handle, "diskused", diskused) ########### End Check Disk ########### # Sleep before the next iteration time.sleep(repy_constants.CPU_POLLING_FREQ_LINUX)