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 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 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 generate_eventhandle(): """ <Purpose> Generates a string event handle that can be used to uniquely identify an event. It is formatted so that cursory verification can be performed. <Returns> A string event handle. """ # Get a unique handle from idhelper uniqueh = idhelper.getuniqueid() # Return the unique handle prefixed with EVENT_PREFIX return (EVENT_PREFIX + uniqueh)
# Let the code string get GC'ed usercode = None # 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)
usercode = None # 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:
print '=' * 40 # 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:
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()
except CodeUnsafeError, e: print "Specified repy program is unsafe!" 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