def execute_namespace_until_completion(thisnamespace, thiscontext): # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # add my thread to the set of threads that are used... event_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', event_id) except Exception as e: tracebackrepy.handle_internalerror("Failed to acquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) try: thisnamespace.evaluate(thiscontext) except SystemExit: raise except: # I think it makes sense to exit if their code throws an exception... tracebackrepy.handle_exception() harshexit.harshexit(6) finally: nanny.tattle_remove_item('events', event_id) # I've changed to the threading library, so this should increase if there are # pending events while threading.activeCount() > idlethreadcount: # do accounting here? time.sleep(0.25) # Once there are no more events, return... return
def execute_namespace_until_completion(thisnamespace, thiscontext): # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # add my thread to the set of threads that are used... event_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', event_id) except Exception, e: tracebackrepy.handle_internalerror("Failed to acquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140)
def createthread(function): """ <Purpose> Creates a new thread of execution. <Arguments> function: The function to invoke on entering the new thread. <Exceptions> RepyArgumentError is raised if the function is not callable. ResourceExhaustedError is raised if there are no available events. <Side Effects> Launches a new thread. <Resource Consumption> Consumes an event. <Returns> None """ # Check if the function is callable if not safe_callable(function): raise RepyArgumentError("Provided function is not callable!") # Generate a unique handle and see if there are resources available eventhandle = EVENT_PREFIX + idhelper.getuniqueid() nanny.tattle_add_item('events', eventhandle) # Wrap the provided function def wrapped_func(): try: function() except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) finally: # Remove the event before I exit nanny.tattle_remove_item('events', eventhandle) # Create a thread object tobj = threading.Thread(target=wrapped_func, name=idhelper.get_new_thread_name(EVENT_PREFIX)) # Check if we get an exception trying to create a new thread try: tobj.start() except thread.error: # Set exit code 56, which stands for a Threading Error # The Node manager will detect this and handle it harshexit.harshexit(56)
def __init__(self, filename, create): """ This is an internal initializer. See emulated_open for details. """ # Initialize the fields, otherwise __del__ gets confused # when we throw an exception. This was not a problem when the # logic was in emulated_open, since we would never throw an # exception self.filename = filename self.fobj = None self.seek_lock = threading.Lock() self.filesize = 0 # raise an RepyArgumentError if the filename isn't valid _assert_is_allowed_filename(filename) # Check the type of create if type(create) is not bool: raise RepyArgumentError( "Create argument type is invalid! Must be a Boolean!") OPEN_FILES_LOCK.acquire() try: # I am not checking whether this file is already opened, I will allow two fd's # on the same file. This behaviour is normal with python in windows and linux. # Here is where we try to allocate a "file" resource from the # nanny system. We will restore this below if there is an exception # This may raise a ResourceExhautedError nanny.tattle_add_item('filesopened', self.filename) # When a file is opened in "r+", it will only succeed if the file already exists # this will work when create is set to False, I catch the exception and raise RepyError # this avoids the need to explicitly check with the create flag. # Store a file handle. try: self.fobj = safe_open(self.filename, "w+b" if create else "r+b") except IOError: raise FileNotFoundError('Cannot openfile non-existent file "' + filename + '" without creating it!') # I am not sure what will cause this exception, I will leave it for now, this won't have # any performance impact. except RepyException: # Restore the file handle we tattled nanny.tattle_remove_item('filesopened', self.filename) raise finally: OPEN_FILES_LOCK.release()
def createthread(function): """ <Purpose> Creates a new thread of execution. <Arguments> function: The function to invoke on entering the new thread. <Exceptions> RepyArgumentError is raised if the function is not callable. ResourceExhaustedError is raised if there are no available events. <Side Effects> Launches a new thread. <Resource Consumption> Consumes an event. <Returns> None """ # Check if the function is callable if not safe_callable(function): raise RepyArgumentError("Provided function is not callable!") # Generate a unique handle and see if there are resources available eventhandle = EVENT_PREFIX + idhelper.getuniqueid() nanny.tattle_add_item('events', eventhandle) # Wrap the provided function def wrapped_func(): try: function() except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) finally: # Remove the event before I exit nanny.tattle_remove_item('events',eventhandle) # Create a thread object tobj = threading.Thread(target=wrapped_func, name=idhelper.get_new_thread_name(EVENT_PREFIX)) # Check if we get an exception trying to create a new thread try: tobj.start() except thread.error: # Set exit code 56, which stands for a Threading Error # The Node manager will detect this and handle it harshexit.harshexit(56)
def __init__(self, filename, create): """ This is an internal initializer. See emulated_open for details. """ # Initialize the fields, otherwise __del__ gets confused # when we throw an exception. This was not a problem when the # logic was in emulated_open, since we would never throw an # exception self.filename = filename self.fobj = None self.seek_lock = threading.Lock() self.filesize = 0 # raise an RepyArgumentError if the filename isn't valid _assert_is_allowed_filename(filename) # Check the type of create if type(create) is not bool: raise RepyArgumentError("Create argument type is invalid! Must be a Boolean!") OPEN_FILES_LOCK.acquire() try: # I am not checking whether this file is already opened, I will allow two fd's # on the same file. This behaviour is normal with python in windows and linux. # Here is where we try to allocate a "file" resource from the # nanny system. We will restore this below if there is an exception # This may raise a ResourceExhautedError nanny.tattle_add_item('filesopened', self.filename) # When a file is opened in "r+", it will only succeed if the file already exists # this will work when create is set to False, I catch the exception and raise RepyError # this avoids the need to explicitly check with the create flag. # Store a file handle. try: self.fobj = safe_open(self.filename, "w+b" if create else "r+b") except IOError: raise FileNotFoundError('Cannot openfile non-existent file "'+filename+'" without creating it!') # I am not sure what will cause this exception, I will leave it for now, this won't have # any performance impact. except RepyException: # Restore the file handle we tattled nanny.tattle_remove_item('filesopened', self.filename) raise finally: OPEN_FILES_LOCK.release()
def settimer(waittime, function, args): """ <Purpose> Allow the current event to set an event to be performed in the future. This does not guarantee the event will be triggered at that time, only that it will be triggered after that time. <Arguments> waittime: The minimum amount of time to wait before delivering the event function: The function to call args: The arguments to pass to the function. This should be a tuple or list <Exceptions> None. <Side Effects> None. <Returns> A timer handle, for use with canceltimer """ restrictions.assertisallowed('settimer', waittime) eventhandle = generate_eventhandle() nanny.tattle_add_item('events', eventhandle) tobj = threading.Timer(waittime, functionwrapper, [function] + [eventhandle] + [args]) # Set the name of the thread tobj.setName(idhelper.get_new_thread_name(EVENT_PREFIX)) timerinfo[eventhandle] = {'timer': tobj} # Check if we get an exception trying to create a new thread try: # start the timer tobj.start() except thread.error, exp: # Set exit code 56, which stands for a Threading Error # The Node manager will detect this and handle it harshexit.harshexit(56)
def settimer(waittime, function, args): """ <Purpose> Allow the current event to set an event to be performed in the future. This does not guarantee the event will be triggered at that time, only that it will be triggered after that time. <Arguments> waittime: The minimum amount of time to wait before delivering the event function: The function to call args: The arguments to pass to the function. This should be a tuple or list <Exceptions> None. <Side Effects> None. <Returns> A timer handle, for use with canceltimer """ restrictions.assertisallowed('settimer',waittime) eventhandle = generate_eventhandle() nanny.tattle_add_item('events',eventhandle) tobj = threading.Timer(waittime,functionwrapper,[function] + [eventhandle] + [args]) # Set the name of the thread tobj.setName(idhelper.get_new_thread_name(EVENT_PREFIX)) timerinfo[eventhandle] = {'timer':tobj} # Check if we get an exception trying to create a new thread try: # start the timer tobj.start() except thread.error, exp: # Set exit code 56, which stands for a Threading Error # The Node manager will detect this and handle it harshexit.harshexit(56)
def __init__(self, filename, create): """ This is an internal initializer. See emulated_open for details. """ # Initialize the fields, otherwise __del__ gets confused # when we throw an exception. This was not a problem when the # logic was in emulated_open, since we would never throw an # exception self.filename = filename self.abs_filename = None self.fobj = None self.seek_lock = threading.Lock() self.filesize = 0 # raise an RepyArgumentError if the filename isn't valid _assert_is_allowed_filename(filename) # Check the type of create if type(create) is not bool: raise RepyArgumentError("Create argument type is invalid! Must be a Boolean!") OPEN_FILES_LOCK.acquire() try: # Check if the file is in use if filename in OPEN_FILES: raise FileInUseError('Cannot open file "'+filename+'" because it is already open!') # Get the absolute file name self.abs_filename = os.path.abspath(os.path.join(repy_constants.REPY_CURRENT_DIR, filename)) # Here is where we try to allocate a "file" resource from the # nanny system. We will restore this below if there is an exception # This may raise a ResourceExhautedError nanny.tattle_add_item('filesopened', self.abs_filename) # charge for checking if the file exists. nanny.tattle_quantity('fileread', 4096) exists = os.path.isfile(self.abs_filename) # if there isn't a file already... if not exists: # if we shouldn't create it, it's an error if not create: raise FileNotFoundError('Cannot openfile non-existent file "'+filename+'" without creating it!') # okay, we should create it... nanny.tattle_quantity('filewrite', 4096) safe_open(self.abs_filename, "w").close() # Forces file creation # Store a file handle # Always open in mode r+b, this avoids Windows text-mode # quirks, and allows reading and writing self.fobj = safe_open(self.abs_filename, "r+b") # Add the filename to the open files OPEN_FILES.add(filename) # Get the file's size self.filesize = os.path.getsize(self.abs_filename) except RepyException: # Restore the file handle we tattled nanny.tattle_remove_item('filesopened', self.abs_filename) raise finally: OPEN_FILES_LOCK.release()
# If we are in "simple execution" mode, execute and exit if simpleexec: main_namespace.evaluate(usercontext) sys.exit(0) # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # call the initialize function usercontext['callfunc'] = 'initialize' usercontext['callargs'] = args[:] initialize_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', initialize_id) except Exception, e: tracebackrepy.handle_internalerror("Failed to aquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) try: main_namespace.evaluate(usercontext) except SystemExit: raise except: # I think it makes sense to exit if their code throws an exception... tracebackrepy.handle_exception() harshexit.harshexit(6) finally: nanny.tattle_remove_item('events', initialize_id)
def __init__(self, filename, mode="r", create=False): """ <Purpose> Allows the user program to open a file safely. This function is not meant to resemble the builtin "open". <Arguments> filename: The file that should be operated on mode: The mode: "r": Open the file for reading. "rw": Open the file for reading and writing. These are the only valid modes accepted by this version of open(). Note: files are always opened in "binary" mode. create: If True, create the file if it doesn't exist already. <Exceptions> As with open, this may raise a number of errors. Additionally: ValueError is raised if this is passed an invalid mode. <Side Effects> Opens a file on disk, using a file descriptor. <Returns> A file-like object """ # Only allow 'r' and 'rw'. actual_mode = None if mode == "r": actual_mode = "rb" elif mode == "rw": actual_mode = "r+b" if actual_mode is None: raise ValueError("Valid modes for opening a file in repy are 'r' and 'rw'.") restrictions.assertisallowed("file.__init__", filename, actual_mode) # Here we are checking that we only open a given file once in 'write' mode # so that file access is more uniform across platforms. (On Microsoft # Windows, for example, writing to the same file from two different file- # handles throws an error because of the way Windows (by default) locks # files opened for writing.) fileinfolock.acquire() try: # Check the entire fileinfo dictionary for the same file already being # open. for fileinfokey in fileinfo.keys(): # If the filename matches this one, raise an exception. if os.path.abspath(fileinfo[fileinfokey]["filename"]) == os.path.abspath(filename): raise ValueError("A file is only allowed to have one open filehandle.") _assert_is_allowed_filename(filename) # If the file doesn't exist and the create flag was passed, create the # file first. if create and not os.path.exists(filename): # Create a file by opening it in write mode and then closing it. restrictions.assertisallowed("file.__init__", filename, "wb") # Allocate a resource. try: nanny.tattle_add_item("filesopened", self.filehandle) except Exception: # Ok, maybe we can free up a file by garbage collecting. gc.collect() nanny.tattle_add_item("filesopened", self.filehandle) # Create the file, and then free up the resource. created_file = myfile(filename, "wb") created_file.close() nanny.tattle_remove_item("filesopened", self.filehandle) self.filehandle = idhelper.getuniqueid() # Here is where we try to allocate a "file" resource from the # nanny system. If that fails, we garbage collect and try again # (this forces __del__() methods to be called on objects with # no references, which is how we automatically free up # file resources). try: nanny.tattle_add_item("filesopened", self.filehandle) except Exception: # Ok, maybe we can free up a file by garbage collecting. gc.collect() nanny.tattle_add_item("filesopened", self.filehandle) fileinfo[self.filehandle] = { "filename": filename, "mode": actual_mode, "fobj": myfile(filename, actual_mode), } self.name = filename self.mode = mode finally: fileinfolock.release()
def __init__(self, filename, mode="r", create=False): """ <Purpose> Allows the user program to open a file safely. This function is not meant to resemble the builtin "open". <Arguments> filename: The file that should be operated on mode: The mode: "r": Open the file for reading. "rw": Open the file for reading and writing. These are the only valid modes accepted by this version of open(). Note: files are always opened in "binary" mode. create: If True, create the file if it doesn't exist already. <Exceptions> As with open, this may raise a number of errors. Additionally: ValueError is raised if this is passed an invalid mode. <Side Effects> Opens a file on disk, using a file descriptor. <Returns> A file-like object """ # Only allow 'r' and 'rw'. actual_mode = None if mode == "r": actual_mode = "rb" elif mode == "rw": actual_mode = "r+b" if actual_mode is None: raise ValueError("Valid modes for opening a file in repy are 'r' and 'rw'.") restrictions.assertisallowed('file.__init__', filename, actual_mode) # Here we are checking that we only open a given file once in 'write' mode # so that file access is more uniform across platforms. (On Microsoft # Windows, for example, writing to the same file from two different file- # handles throws an error because of the way Windows (by default) locks # files opened for writing.) fileinfolock.acquire() try: # Check the entire fileinfo dictionary for the same file already being # open. for fileinfokey in fileinfo.keys(): # If the filename matches this one, raise an exception. if os.path.abspath(fileinfo[fileinfokey]['filename']) == \ os.path.abspath(filename): raise ValueError(\ "A file is only allowed to have one open filehandle.") _assert_is_allowed_filename(filename) # If the file doesn't exist and the create flag was passed, create the # file first. if create and not os.path.exists(filename): # Create a file by opening it in write mode and then closing it. restrictions.assertisallowed('file.__init__', filename, 'wb') # Allocate a resource. try: nanny.tattle_add_item('filesopened', self.filehandle) except Exception: # Ok, maybe we can free up a file by garbage collecting. gc.collect() nanny.tattle_add_item('filesopened', self.filehandle) # Create the file, and then free up the resource. created_file = myfile(filename, 'wb') created_file.close() nanny.tattle_remove_item('filesopened', self.filehandle) self.filehandle = idhelper.getuniqueid() # Here is where we try to allocate a "file" resource from the # nanny system. If that fails, we garbage collect and try again # (this forces __del__() methods to be called on objects with # no references, which is how we automatically free up # file resources). try: nanny.tattle_add_item('filesopened', self.filehandle) except Exception: # Ok, maybe we can free up a file by garbage collecting. gc.collect() nanny.tattle_add_item('filesopened', self.filehandle) fileinfo[self.filehandle] = {'filename':filename, \ 'mode':actual_mode, 'fobj':myfile(filename, actual_mode)} self.name = filename self.mode = mode finally: fileinfolock.release()
def __init__(self, filename, create): """ This is an internal initializer. See emulated_open for details. """ # Initialize the fields, otherwise __del__ gets confused # when we throw an exception. This was not a problem when the # logic was in emulated_open, since we would never throw an # exception self.filename = filename self.abs_filename = None self.fobj = None self.seek_lock = threading.Lock() self.filesize = 0 # raise an RepyArgumentError if the filename isn't valid _assert_is_allowed_filename(filename) # Check the type of create if type(create) is not bool: raise RepyArgumentError( "Create argument type is invalid! Must be a Boolean!") OPEN_FILES_LOCK.acquire() try: # Check if the file is in use if filename in OPEN_FILES: raise FileInUseError('Cannot open file "' + filename + '" because it is already open!') # Get the absolute file name self.abs_filename = os.path.abspath( os.path.join(repy_constants.REPY_CURRENT_DIR, filename)) # Here is where we try to allocate a "file" resource from the # nanny system. We will restore this below if there is an exception # This may raise a ResourceExhautedError nanny.tattle_add_item('filesopened', self.abs_filename) # charge for checking if the file exists. nanny.tattle_quantity('fileread', 4096) exists = os.path.isfile(self.abs_filename) # if there isn't a file already... if not exists: # if we shouldn't create it, it's an error if not create: raise FileNotFoundError( 'Cannot openfile non-existent file "' + filename + '" without creating it!') # okay, we should create it... nanny.tattle_quantity('filewrite', 4096) safe_open(self.abs_filename, "w").close() # Forces file creation # Store a file handle # Always open in mode r+b, this avoids Windows text-mode # quirks, and allows reading and writing self.fobj = safe_open(self.abs_filename, "r+b") # Add the filename to the open files OPEN_FILES.add(filename) # Get the file's size self.filesize = os.path.getsize(self.abs_filename) except RepyException: # Restore the file handle we tattled nanny.tattle_remove_item('filesopened', self.abs_filename) raise finally: OPEN_FILES_LOCK.release()
# If we are in "simple execution" mode, execute and exit if simpleexec: main_namespace.evaluate(usercontext) sys.exit(0) # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # call the initialize function usercontext['callfunc'] = 'initialize' usercontext['callargs'] = args[:] event_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', event_id) except Exception, e: tracebackrepy.handle_internalerror("Failed to aquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) try: if profile: p = cProfile.Profile() p.runctx('main_namespace.evaluate(usercontext)', globals(), locals(),) p = pstats.Stats(p) # p.sort_stats('cumulative') p.print_stats() else: main_namespace.evaluate(usercontext) except SystemExit: raise
print "Static-code analysis failed with error: " + str(e) harshexit.harshexit(5) # Let the code string get GC'ed usercode = None # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # call the initialize function usercontext['callfunc'] = 'initialize' usercontext['callargs'] = args[:] event_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', event_id) except Exception, e: tracebackrepy.handle_internalerror("Failed to aquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) return main_namespace.code, main_namespace.get_safe_context(usercontext) def finalize(): global idlethreadcount, event_id nanny.tattle_remove_item('events', event_id) # I've changed to the threading library, so this should increase if there are # pending events while threading.activeCount() > idlethreadcount: