def win_check_cpu_use(cpulim, pid): global winlastcpuinfo # get use information and time... now = getruntime() # Get the total cpu time usertime = windows_api.get_process_cpu_time(pid) useinfo = [usertime, now] # get the previous time and cpu so we can compute the percentage oldusertime = winlastcpuinfo[0] oldnow = winlastcpuinfo[1] if winlastcpuinfo == [0,0]: winlastcpuinfo = useinfo # give them a free pass if it's their first time... return 0 # save this data for next time... winlastcpuinfo = useinfo # Get the elapsed time... elapsedtime = now - oldnow # This is a problem if elapsedtime == 0: return -1 # Error condition # percent used is the amount of change divided by the time... percentused = (usertime - oldusertime) / elapsedtime # Calculate amount of time to sleep for stoptime = nanny_resource_limits.calculate_cpu_sleep_interval(cpulim, percentused,elapsedtime) if stoptime > 0.0: # Try to timeout the process if windows_api.timeout_process(pid, stoptime): # Log the stoptime process_stopped_timeline.append((now, stoptime)) # Drop the first element if the length is greater than the maximum entries if len(process_stopped_timeline) > process_stopped_max_entries: process_stopped_timeline.pop(0) # Return how long we slept so parent knows whether it should sleep return stoptime else: # Process must have been making system call, try again next time return -1 # If the stop time is 0, then avoid calling timeout_process else: return 0.0
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)