Beispiel #1
0
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
Beispiel #2
0
 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)
Beispiel #3
0
 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)
Beispiel #4
0
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:
        # do accounting here?
        time.sleep(0.25)
    # Once there are no more pending events for the user thread, we exit
    harshexit.harshexit(0)
Beispiel #5
0
    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()
Beispiel #6
0
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:
    # do accounting here?
    time.sleep(0.25)
  # Once there are no more pending events for the user thread, we exit
  harshexit.harshexit(0)
Beispiel #7
0
  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()
Beispiel #8
0
  def __del__(self):
    myfilehandle = self.filehandle

    # Tell nanny we're gone.
    nanny.tattle_remove_item('filesopened', myfilehandle)

    # Take the fileinfo dict lock, delete ourselves, and unlock.
    fileinfolock.acquire()
    try:
      del fileinfo[myfilehandle]['fobj']
      del fileinfo[myfilehandle]
    except KeyError:
      pass
    finally:
      fileinfolock.release()
Beispiel #9
0
    def __del__(self):
        myfilehandle = self.filehandle

        # Tell nanny we're gone.
        nanny.tattle_remove_item("filesopened", myfilehandle)

        # Take the fileinfo dict lock, delete ourselves, and unlock.
        fileinfolock.acquire()
        try:
            del fileinfo[myfilehandle]["fobj"]
            del fileinfo[myfilehandle]
        except KeyError:
            pass
        finally:
            fileinfolock.release()
Beispiel #10
0
    def close(self):
        """
    <Purpose>
      Allows the user program to close the handle to the file.

    <Arguments>
      None.

    <Exceptions>
      FileClosedError is raised if the file is already closed.

    <Resource Consumption>
      Releases a file handle.

    <Returns>
      None.
    """

        # Acquire the lock to the set
        OPEN_FILES_LOCK.acquire()

        # Tell nanny we're gone.
        nanny.tattle_remove_item('filesopened', self.abs_filename)

        # Acquire the seek lock
        self.seek_lock.acquire()

        try:
            # Release the file object
            fobj = self.fobj
            if fobj is not None:
                fobj.close()
                self.fobj = None
            else:
                raise FileClosedError("File '" + str(self.filename) +
                                      "' is already closed!")

            # Remove this file from the list of open files
            OPEN_FILES.remove(self.filename)

        finally:
            # Release the two locks we hold
            self.seek_lock.release()
            OPEN_FILES_LOCK.release()
Beispiel #11
0
def canceltimer(timerhandle):
    """
   <Purpose>
      Cancels a timer.

   <Arguments>
      timerhandle:
         The handle of the timer that should be stopped.   Handles are 
         returned by settimer

   <Exceptions>
      None.

   <Side Effects>
      None.

   <Returns>
      If False is returned, the timer already fired or was cancelled 
      previously.   If True is returned, the timer was cancelled
  """

    restrictions.assertisallowed('canceltimer')

    # Armon: Check that the given handle is valid
    if not is_valid_eventhandle(timerhandle):
        raise Exception("Invalid timer handle specified!")

    try:
        timerinfo[timerhandle]['timer'].cancel()
    except KeyError:
        # The timer already fired (or was cancelled)
        return False

    try:
        del timerinfo[timerhandle]
    except KeyError:
        # The timer just fired (or was cancelled)
        return False
    else:
        # I was able to delete the entry, the function will abort.   I can remove
        # the event
        nanny.tattle_remove_item('events', timerhandle)
        return True
Beispiel #12
0
  def close(self):
    """
    <Purpose>
      Allows the user program to close the handle to the file.

    <Arguments>
      None.

    <Exceptions>
      FileClosedError is raised if the file is already closed.

    <Resource Consumption>
      Releases a file handle.

    <Returns>
      None.
    """

    # Acquire the lock to the set 
    OPEN_FILES_LOCK.acquire()

    # Tell nanny we're gone.
    nanny.tattle_remove_item('filesopened', self.abs_filename)
    
    # Acquire the seek lock
    self.seek_lock.acquire()
  
    try:
      # Release the file object
      fobj = self.fobj
      if fobj is not None:
        fobj.close()
        self.fobj = None
      else:
        raise FileClosedError("File '"+str(self.filename)+"' is already closed!")

      # Remove this file from the list of open files
      OPEN_FILES.remove(self.filename)

    finally:
      # Release the two locks we hold
      self.seek_lock.release()
      OPEN_FILES_LOCK.release()
Beispiel #13
0
def canceltimer(timerhandle):
  """
   <Purpose>
      Cancels a timer.

   <Arguments>
      timerhandle:
         The handle of the timer that should be stopped.   Handles are 
         returned by settimer

   <Exceptions>
      None.

   <Side Effects>
      None.

   <Returns>
      If False is returned, the timer already fired or was cancelled 
      previously.   If True is returned, the timer was cancelled
  """

  restrictions.assertisallowed('canceltimer')

  # Armon: Check that the given handle is valid
  if not is_valid_eventhandle(timerhandle):
    raise Exception("Invalid timer handle specified!")

  try:
    timerinfo[timerhandle]['timer'].cancel()
  except KeyError:
    # The timer already fired (or was cancelled)
    return False

  try:
    del timerinfo[timerhandle]
  except KeyError:
    # The timer just fired (or was cancelled)
    return False
  else:
    # I was able to delete the entry, the function will abort.   I can remove
    # the event
    nanny.tattle_remove_item('events',timerhandle)
    return True
Beispiel #14
0
def functionwrapper(func, timerhandle, args):
  #restrictions ?
  # call the function with the arguments
  try:
    if timerhandle in timerinfo:
      del timerinfo[timerhandle]
    else:
      # I've been "stopped" by canceltimer
      return
  except KeyError:
    # I've been "stopped" by canceltimer
    return
    
  try:
    func(*args)
  except:
    # Exit if they throw an uncaught exception
    tracebackrepy.handle_exception()
    harshexit.harshexit(30)
    
  # remove the event before I exit
  nanny.tattle_remove_item('events',timerhandle)
Beispiel #15
0
def functionwrapper(func, timerhandle, args):
    #restrictions ?
    # call the function with the arguments
    try:
        if timerhandle in timerinfo:
            del timerinfo[timerhandle]
        else:
            # I've been "stopped" by canceltimer
            return
    except KeyError:
        # I've been "stopped" by canceltimer
        return

    try:
        func(*args)
    except:
        # Exit if they throw an uncaught exception
        tracebackrepy.handle_exception()
        harshexit.harshexit(30)

    # remove the event before I exit
    nanny.tattle_remove_item('events', timerhandle)
Beispiel #16
0
  def close(self):
    # prevent TOCTOU race with client changing my filehandle
    myfilehandle = self.filehandle
    restrictions.assertisallowed('file.close')

    # Ignore multiple closes (as file does)
    if myfilehandle not in fileinfo:
      return

    nanny.tattle_remove_item('filesopened',myfilehandle)

    fileinfolock.acquire()
    try:
      returnvalue = fileinfo[myfilehandle]['fobj'].close()

      # delete the filehandle
      del fileinfo[myfilehandle]

    finally:
      fileinfolock.release()

    return returnvalue
Beispiel #17
0
    def close(self):
        """
    <Purpose>
      Allows the user program to close the handle to the file.

    <Arguments>
      None.

    <Exceptions>
      FileClosedError is raised if the file is already closed.

    <Resource Consumption>
      Releases a file handle.

    <Returns>
      None.
    """
        # Acquire the lock to the set
        OPEN_FILES_LOCK.acquire()

        # Tell nanny we're gone.
        nanny.tattle_remove_item('filesopened', self.filename)

        try:
            # Once again, don't explicitly check if the file handle is valid or not
            # allow python to generate an exception and we will catch it.

            # Also, close can be called multiple times on the same file handle. This
            # behaviour is normal with python in linux and windows.

            # Release the file object
            self.fobj.close()
        except AttributeError:
            raise FileClosedError("File '" + str(self.filename) +
                                  "' is already closed!")

        finally:
            # Release the two locks we hold
            OPEN_FILES_LOCK.release()
Beispiel #18
0
    def close(self):
        # prevent TOCTOU race with client changing my filehandle
        myfilehandle = self.filehandle
        restrictions.assertisallowed("file.close")

        # Ignore multiple closes (as file does)
        if myfilehandle not in fileinfo:
            return

        nanny.tattle_remove_item("filesopened", myfilehandle)

        fileinfolock.acquire()
        try:
            returnvalue = fileinfo[myfilehandle]["fobj"].close()

            # delete the filehandle
            del fileinfo[myfilehandle]

        finally:
            fileinfolock.release()

        return returnvalue
Beispiel #19
0
  def close(self):
    """
    <Purpose>
      Allows the user program to close the handle to the file.

    <Arguments>
      None.

    <Exceptions>
      FileClosedError is raised if the file is already closed.

    <Resource Consumption>
      Releases a file handle.

    <Returns>
      None.
    """
    # Acquire the lock to the set 
    OPEN_FILES_LOCK.acquire()

    # Tell nanny we're gone.
    nanny.tattle_remove_item('filesopened', self.filename)
    
    try:
      # Once again, don't explicitly check if the file handle is valid or not
      # allow python to generate an exception and we will catch it.

      # Also, close can be called multiple times on the same file handle. This
      # behaviour is normal with python in linux and windows.

      # Release the file object
      self.fobj.close()
    except AttributeError:
      raise FileClosedError("File '"+str(self.filename)+"' is already closed!")

    finally:
      # Release the two locks we hold
      OPEN_FILES_LOCK.release()
Beispiel #20
0
    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
  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 pending events for the user thread, we exit
  harshexit.harshexit(0)


def usage(str_err=""):
  # Ivan 12/24/2008
  """
Beispiel #21
0
  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)


  # 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 pending events for the user thread, we give them
  # an "exit" event.   This allows them to clean up, etc. if needed.

  # call the user program to notify them that we are exiting...
  usercontext['callfunc'] = 'exit'
Beispiel #22
0
        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
        )

    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 init_repy_location(repy_directory):

    # Translate into an absolute path
    if os.path.isabs(repy_directory):
Beispiel #23
0
  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()
Beispiel #24
0
  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)


  # 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 pending events for the user thread, we give them
  # an "exit" event.   This allows them to clean up, etc. if needed.

  # call the user program to notify them that we are exiting...
  usercontext['callfunc'] = 'exit'
Beispiel #25
0
    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)

    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 init_repy_location(repy_directory):

    # Translate into an absolute path
    if os.path.isabs(repy_directory):
Beispiel #26
0
    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()
Beispiel #27
0
    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()
Beispiel #28
0
  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()