Пример #1
0
def safe_check_subprocess(code):
  """
  <Purpose>
    Runs safe_check() in a subprocess. This is done because the AST safe_check()
    creates uses a large amount of RAM. By running safe_check() in a subprocess
    we can guarantee that the memory will be reclaimed when the process ends.
  
  <Arguments>
    code: See safe_check.
    
  <Exceptions>
    As with safe_check.
  
  <Return>
    See safe_check.
  """
  
  # Get the path to safe_check.py by using the original start directory of python
  path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR, "safe_check.py")
  
  # Start a safety check process, reading from the user code and outputing to a pipe we can read
  proc = subprocess.Popen([sys.executable, path_to_safe_check],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  
  # Write out the user code, close so the other end gets an EOF
  proc.stdin.write(code)
  proc.stdin.close()
  
  # Wait for the process to terminate
  starttime = nonportable.getruntime()

  # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
  while nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT:
    # Did the process finish running?
    if proc.poll() != None:
      break;
    time.sleep(0.02)
  else:
    # Kill the timed-out process
    try:
      harshexit.portablekill(proc.pid)
    except:
      pass
    raise Exception, "Evaluation of code safety exceeded timeout threshold \
                    ("+str(nonportable.getruntime() - starttime)+" seconds)"
  
  # Read the output and close the pipe
  output = proc.stdout.read()
  proc.stdout.close()
  
  # Check the output, None is success, else it is a failure
  if output == "None":
    return True
  
  # If there is no output, this is a fatal error condition
  elif output == "":
    raise Exception, "Fatal error while evaluating code safety!"
    
  else:
    # Raise the error from the output
    raise exception_hierarchy.SafeException, output
def main():
  """
  <Purpose>
    Kills all the seattle programs that are running.

  <Arguments>
    None.
  
  <Exceptions>
    None.

  <Side Effects>
    Kills all the seattle programs that are running.

  <Returns>
    None.
  """
  for lockname in locklist:
    lockstate = runonce.getprocesslock(lockname)
    # If lockstate is a process pid, then we need to terminate it. Otherwise,
    # that lock is not being held by a program that needs to be terminated. 
    if not lockstate == True and not lockstate == False:
      # We got the pid, we can stop the process
      harshexit.portablekill(lockstate)

      # Now acquire the lock for ourselves, looping until we
      # actually get it.
      retrievedlock = runonce.getprocesslock(lockname)
      while retrievedlock != True:
        harshexit.portablekill(retrievedlock)
        retrievedlock = runonce.getprocesslock(lockname)
Пример #3
0
def _stopfile_exit(exitcode, pid):
  # On Windows, we are in the Repy process, so we can just use harshexit
  if harshexit.ostype in ["Windows", "WindowsCE"]:
    # Harshexit will store the appriopriate status for us
    harshexit.harshexit(exitcode)

  else:    # On NIX we are on the external process
    try:
      if exitcode == 44:
        # Write out status information, repy was Stopped
        statusstorage.write_status("Stopped")  
      else:
        # Status terminated
        statusstorage.write_status("Terminated")
    except:
      pass

    # Disable the other status thread, in case the resource thread detects we've killed repy
    statusstorage.init(None)

    # Kill repy
    harshexit.portablekill(pid)

    # Fix Derek proposed, this should solve the problem of 
    # the monitor exiting before the repy process.
    time.sleep(1)

    # Exit
    harshexit.harshexit(78)
Пример #4
0
def _stopfile_exit(exitcode, pid):
    # On Windows, we are in the Repy process, so we can just use harshexit
    if harshexit.ostype in ["Windows", "WindowsCE"]:
        # Harshexit will store the appriopriate status for us
        harshexit.harshexit(exitcode)

    else:  # On NIX we are on the external process
        try:
            if exitcode == 44:
                # Write out status information, repy was Stopped
                statusstorage.write_status("Stopped")
            else:
                # Status terminated
                statusstorage.write_status("Terminated")
        except:
            pass

        # Disable the other status thread, in case the resource thread detects we've killed repy
        statusstorage.init(None)

        # Kill repy
        harshexit.portablekill(pid)

        # Fix Derek proposed, this should solve the problem of
        # the monitor exiting before the repy process.
        time.sleep(1)

        # Exit
        harshexit.harshexit(78)
Пример #5
0
def main():
    """
  <Purpose>
    Kills all the seattle programs that are running.

  <Arguments>
    None.
  
  <Exceptions>
    None.

  <Side Effects>
    Kills all the seattle programs that are running.

  <Returns>
    None.
  """
    for lockname in locklist:
        lockstate = runonce.getprocesslock(lockname)
        # If lockstate is a process pid, then we need to terminate it. Otherwise,
        # that lock is not being held by a program that needs to be terminated.
        if not lockstate == True and not lockstate == False:
            # We got the pid, we can stop the process
            harshexit.portablekill(lockstate)

            # Now acquire the lock for ourselves, looping until we
            # actually get it.
            retrievedlock = runonce.getprocesslock(lockname)
            while retrievedlock != True:
                harshexit.portablekill(retrievedlock)
                retrievedlock = runonce.getprocesslock(lockname)
Пример #6
0
def safe_check(code):
    """Check the code to be safe."""
    return True
    # NOTE: This code will not work in Windows Mobile due to the reliance on subprocess

    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR,
                                      "safe_check.py")

    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen(["python", path_to_safe_check],
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)

    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()

    # Wait for the process to terminate
    starttime = nonportable.getruntime()
    status = None

    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while status == None and (nonportable.getruntime() - starttime <
                              EVALUTATION_TIMEOUT):
        status = proc.poll()
        time.sleep(0.02)

    else:
        # Check if the process is still running
        if status == None:
            # Try to terminate the external process
            try:
                harshexit.portablekill(proc.pid)
            except:
                pass

            # Raise an exception
            raise Exception, "Evaluation of code safety exceeded timeout threshold (" + str(
                nonportable.getruntime() - starttime) + " seconds)"

    # Read the output and close the pipe
    output = proc.stdout.read()
    proc.stdout.close()

    # Check the output, None is success, else it is a failure
    if output == "None":
        return True

    # If there is no output, this is a fatal error condition
    elif output == "":
        raise Exception, "Fatal error while evaluating code safety!"

    else:
        # Raise the error from the output
        raise exception_hierarchy.SafeException, output
Пример #7
0
 def stop_nm():
   # Stop the NM
   gotlock = runonce.getprocesslock("seattlenodemanager")
   if gotlock == True:
     # No NM running? This is an error
     logstream.write("FAILURE: Successfully acquired the NM process lock! The NM should be running!\n")
   else:
     if gotlock:
       # Kill the NM
       harshexit.portablekill(gotlock)
       # Allow the sockets to cleanup and the locks to be cleaned
       time.sleep(3)
Пример #8
0
 def stop_nm():
   # Stop the NM
   gotlock = runonce.getprocesslock("seattlenodemanager")
   if gotlock == True:
     # No NM running? This is an error
     logstream.write("FAILURE: Successfully acquired the NM process lock! The NM should be running!\n")
   else:
     if gotlock:
       # Kill the NM
       harshexit.portablekill(gotlock)
       # Allow the sockets to cleanup and the locks to be cleaned
       time.sleep(3)
Пример #9
0
def safe_check(code):
    """Check the code to be safe."""
    return True
    # NOTE: This code will not work in Windows Mobile due to the reliance on subprocess
    
    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR, "safe_check.py")
    
    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen(["python", path_to_safe_check],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    
    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()
    
    # Wait for the process to terminate
    starttime = nonportable.getruntime()
    status = None
    
    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while status == None and (nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT):
      status = proc.poll()
      time.sleep(0.02)
      
    else:
      # Check if the process is still running
      if status == None:
        # Try to terminate the external process
        try:
          harshexit.portablekill(proc.pid)
        except:
          pass
      
        # Raise an exception
        raise Exception, "Evaluation of code safety exceeded timeout threshold ("+str(nonportable.getruntime() - starttime)+" seconds)"
    
    
    # Read the output and close the pipe
    output = proc.stdout.read()
    proc.stdout.close()
    
    # Check the output, None is success, else it is a failure
    if output == "None":
      return True
    
    # If there is no output, this is a fatal error condition
    elif output == "":
      raise Exception, "Fatal error while evaluating code safety!"
      
    else:
      # Raise the error from the output
      raise exception_hierarchy.SafeException, output
Пример #10
0
def restart_client(filenamelist):
    """
  <Purpose>
    Restarts the node manager.

  <Arguments>
    filenamelist - Currently not used, but is included for possible future use.

  <Exceptions>
    None

  <Side Effects>
    The current node manager is killed, and a new one is started.

  <Returns>
    None.
  """
    # kill nmmain if it is currently running
    retval = runonce.getprocesslock('seattlenodemanager')
    if retval == True:
        safe_log(
            "[restart_client] Obtained the lock 'seattlenodemanager', it wasn't running."
        )
        # I got the lock, it wasn't running...
        # we want to start a new one, so lets release
        runonce.releaseprocesslock('seattlenodemanager')
    elif retval == False:
        # Someone has the lock, but I can't do anything...
        safe_log(
            "[restart_client] The lock 'seattlenodemanager' is held by an unknown process. Will try to start it anyways."
        )
    else:
        safe_log("[restart_client] Stopping the nodemanager.")
        # I know the process ID!   Let's stop the process...
        harshexit.portablekill(retval)

    safe_log("[restart_client] Starting the nodemanager.")

    # run the node manager.   I rely on it to do the smart thing (handle multiple
    # instances, etc.)
    nm_restart_command_args_list = ["python", "nmmain.py"]

    if run_nodemanager_in_foreground:
        nm_restart_command_args_list.append('--foreground')

    junkprocessobject = portable_popen.Popen(nm_restart_command_args_list)
Пример #11
0
  def _internal_error(message):
    try:
      print >> sys.stderr, message
      sys.stderr.flush()
    except:
      pass
      
    # Stop the nmstatusinterface, we don't want any more status updates
    nmstatusinterface.stop()  

    # Kill repy
    harshexit.portablekill(childpid)

    try:
      # Write out status information, repy was Stopped
      statusstorage.write_status("Terminated")  
    except:
      pass
Пример #12
0
def stoptest(socket,pid):
  """
  <Purpose>
    Checks the socket for any incoming user messages while the test is running.
    If the user sends 'cancel' to us, we will kill the running test.
  
  <Arguments>
    socket: A TCP socket to read from
    pid: The PID of the process to kill.
  """

  try:
    mesg = socket.recv(8)
    print "Incoming message:",mesg
    if "cancel" in mesg:
      harshexit.portablekill(pid)
  except:
    pass
Пример #13
0
def restart_client(filenamelist):
    """
  <Purpose>
    Restarts the node manager.

  <Arguments>
    filenamelist - Currently not used, but is included for possible future use.

  <Exceptions>
    None

  <Side Effects>
    The current node manager is killed, and a new one is started.

  <Returns>
    None.
  """
    # kill nmmain if it is currently running
    retval = runonce.getprocesslock("seattlenodemanager")
    if retval == True:
        safe_log("[restart_client] Obtained the lock 'seattlenodemanager', it wasn't running.")
        # I got the lock, it wasn't running...
        # we want to start a new one, so lets release
        runonce.releaseprocesslock("seattlenodemanager")
    elif retval == False:
        # Someone has the lock, but I can't do anything...
        safe_log(
            "[restart_client] The lock 'seattlenodemanager' is held by an unknown process. Will try to start it anyways."
        )
    else:
        safe_log("[restart_client] Stopping the nodemanager.")
        # I know the process ID!   Let's stop the process...
        harshexit.portablekill(retval)

    safe_log("[restart_client] Starting the nodemanager.")

    # run the node manager.   I rely on it to do the smart thing (handle multiple
    # instances, etc.)
    nm_restart_command_args_list = ["python", "nmmain.py"]

    if run_nodemanager_in_foreground:
        nm_restart_command_args_list.append("--foreground")

    junkprocessobject = portable_popen.Popen(nm_restart_command_args_list)
Пример #14
0
def safe_check_subprocess(code):
    """
  <Purpose>
    Runs safe_check() in a subprocess. This is done because the AST
    safe_check() uses a large amount of RAM. By running safe_check() in a
    subprocess we can guarantee that the memory will be reclaimed when the
    process ends.
  
  <Arguments>
    code: See safe_check.
    
  <Exceptions>
    As with safe_check.
  
  <Return>
    See safe_check.
  """

    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR,
                                      "safe_check.py")

    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen([sys.executable, path_to_safe_check],
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)

    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()

    # Wait for the process to terminate
    starttime = nonportable.getruntime()

    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT:
        # Did the process finish running?
        if proc.poll() != None:
            break
        time.sleep(0.02)
    else:
        # Kill the timed-out process
        try:
            harshexit.portablekill(proc.pid)
        except:
            pass
        raise Exception, "Evaluation of code safety exceeded timeout threshold \
                    (" + str(nonportable.getruntime() -
                             starttime) + " seconds)"

    # Read the output and close the pipe
    rawoutput = proc.stdout.read()
    proc.stdout.close()

    # Interim fix for SeattleTestbed/attic#1080:
    # Get rid of stray debugging output on Android of the form
    # `dlopen libpython2.6.so` and `dlopen /system/lib/libc.so`,
    # yet preserve all of the other output (including empty lines).

    if IS_ANDROID:
        output = ""
        for line in rawoutput.split("\n"):
            # Preserve empty lines
            if line == "":
                output += "\n"
                continue
            # Suppress debug messages we know can turn up
            wordlist = line.split()
            if wordlist[0] == "dlopen":
                if wordlist[-1] == "/system/lib/libc.so":
                    continue
                if wordlist[-1].startswith("libpython") and \
                  wordlist[-1].endswith(".so"):
                    # We expect "libpython" + version number + ".so".
                    # The version number should be a string convertible to float.
                    # If it's not, raise an exception.
                    try:
                        versionstring = (wordlist[-1].replace("libpython",
                                                              "")).replace(
                                                                  ".so", "")
                        junk = float(versionstring)
                    except TypeError, ValueError:
                        raise Exception("Unexpected debug output '" + line +
                                        "' while evaluating code safety!")
            else:
                output += line + "\n"

        # Strip off the last newline character we added
        output = output[0:-1]
Пример #15
0
# without closing stdin, stdout, stderr, nmmain.py won't execute on XP
nmproc.stdin.close()
nmproc.stdout.close()
nmproc.stderr.close()

try:
    # We'll want to kill this once we are told to do so... (sys.stdin.close() is
    # the signal)
    sys.stdin.read()
except KeyboardInterrupt:
    # the user interrupted us, let's clean up!
    print
    print 'Cleaning up the subprocess'

# We need the PID.   Since the node manager daemonizes, this isn't the pid of
# nmproc.   We can get the PID from the log
nodemanagerlogfo = open('v2' + os.sep + 'nodemanager.old')

firstline = nodemanagerlogfo.readline()

# an entry looks like this:
# 1292537407.82:PID-27493:[INFO]: Running nodemanager in test mode
# let's get the PID out as a number...
pidportion = firstline.split(':')[1]
assert (pidportion.startswith('PID-'))
nmpid = int(pidportion[4:])

# let's terminate the node manager...
harshexit.portablekill(nmpid)
Пример #16
0
def main():

  repy_args = [sys.executable, 'repy.py', 
               'restrictions.default',
               'test_killp_writetodisk.py']

  
  if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':

    process = subprocess.Popen(repy_args, 
                               stdout = subprocess.PIPE, 
                               stderr = subprocess.PIPE)
    pid = process.pid

    # Give it a few seconds to start.
    time.sleep(4)


    # Find the orphaned child's PID.

    # Run <ps> and print the first field (PID) of the line with second 
    # field (PPID) equal to the parent pid.
    if nonportable.ostype == 'Darwin' or nonportable.osrealtype == 'FreeBSD':
      command = "ps -aO ppid | awk '{if ($2==" + str(pid) + ") {print $1}}'"      
    elif nonportable.ostype == 'Linux':
      command = "ps -ef | awk '{if ($3==" + str(pid) + ") {print $2}}'"

    (out, error) = subprocess.Popen(command,
                                    stdout = subprocess.PIPE, 
                                    stderr = subprocess.PIPE, 
                                    shell = True).communicate()
    child_pid = out.strip()

  # Windows 
  elif nonportable.ostype == 'Windows' or nonportable.ostype == 'WindowsCE':
    # This is much easier because we don't worry about the path or have 
    # children to worry about.
    process = subprocess.Popen(repy_args,
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE)

    pid = process.pid
    
    # Wait while the process starts.
    time.sleep(4)

  else:
    print "Error: Unknown OS type '" + nonportable.ostype + "'!"
    sys.exit(1)



  # Kill the repy resource monitor.
  harshexit.portablekill(pid)
  time.sleep(1)
  
  # See ticket #413 and #421
  # This is a workaround for the possibility that the repy child was sleeping
  if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
    # Send SIGCONT to the child if the process still exists, it should wake up,
    # get a read error when checking the pipe, and then exit...
    try: os.kill(int(child_pid), signal.SIGCONT)
    except OSError: pass # The child has likely exited
      
    # Wait for the signal to take effect
    time.sleep(1)    

  # Make sure the file size is not changing
  firstsize = os.path.getsize("junk_test.out")
  time.sleep(1)
  secondsize = os.path.getsize("junk_test.out")
  

  if firstsize != secondsize: print 'FAIL'
Пример #17
0
def run_test(arguments, tmpdir, socket):
  """
  <Purpose>
    Runs the actual test while streaming the results back to the user.

  <Arguments>
    arguments: The command to executed, will be prepended with 'python '
    tmpdir: The temporary directory which we should execute in
    socket: A TCP socket to stream the results back on.

  <Side Effects>
    Launches a new process.

  <Returns>
    Nothing.
  """
  global INITIAL_CONFIG
  enable_stderr = INITIAL_CONFIG["stderr"]
  path = INITIAL_CONFIG["path"]
  use_shell = INITIAL_CONFIG["shell"]

  # Inform the user what is happening  
  if not enable_stderr:
    socket.send("NOTE: stderr will be deferred until program exits.\n")

  # Go into the temporary directory
  originaldir = os.getcwd()
  os.chdir(tmpdir)
  try:
    # Start time
    start = time.time()

    # Launch the process
    proc = subprocess.Popen(path+" "+arguments,shell=use_shell,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    pid = proc.pid 
   
    # Setup a thread to check for an interrupt request
    settimer(0, stoptest,(socket,pid))

    # Read the data from stdout and send it, timeout after 10 minutes
    while proc.poll() == None and time.time() - start < 600:
      # Enable stderr by default, disable on some systems (Windows)
      # On windows select cannot be used, defer stderr
      if enable_stderr:
        try:
          # Check for ready sockets
          (rdy,wrt,excep) = select.select([proc.stdout, proc.stderr],[],[],SAMPLE_RATE)
        except Exception, e:
          rdy = []
      
        # Get data from each ready handle
        data = ""
        for handle in rdy:
          data += handle.read(CHUNK_SIZE)
        # If there is any data, write it out
        if data != "":
          socket.send(data)
      else:
        # Only check stderr until the then
        data = proc.stdout.read(CHUNK_SIZE)
        if data != "": socket.send(data)
        time.sleep(SAMPLE_RATE)        

    # Done, flush any remaining data
    data = proc.stdout.read()
    data += proc.stderr.read()
    if data != "":
      socket.send(data)
    proc.stdout.close()
    proc.stderr.close()

    # Kill the process if it is still running
    if proc.poll() == None:
      harshexit.portablekill(pid)
Пример #18
0
def safe_check_subprocess(code):
    """
  <Purpose>
    Runs safe_check() in a subprocess. This is done because the AST safe_check()
    creates uses a large amount of RAM. By running safe_check() in a subprocess
    we can guarantee that the memory will be reclaimed when the process ends.
  
  <Arguments>
    code: See safe_check.
    
  <Exceptions>
    As with safe_check.
  
  <Return>
    See safe_check.
  """

    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR,
                                      "safe_check.py")

    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen([sys.executable, path_to_safe_check],
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)

    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()

    # Wait for the process to terminate
    starttime = nonportable.getruntime()

    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT:
        # Did the process finish running?
        if proc.poll() != None:
            break
        time.sleep(0.02)
    else:
        # Kill the timed-out process
        try:
            harshexit.portablekill(proc.pid)
        except:
            pass
        raise Exception, "Evaluation of code safety exceeded timeout threshold \
                    (" + str(nonportable.getruntime() -
                             starttime) + " seconds)"

    # Read the output and close the pipe
    output = proc.stdout.read()
    proc.stdout.close()

    # Check the output, None is success, else it is a failure
    if output == "None":
        return True

    # If there is no output, this is a fatal error condition
    elif output == "":
        raise Exception, "Fatal error while evaluating code safety!"

    else:
        # Raise the error from the output
        raise exception_hierarchy.SafeException, output
Пример #19
0
def safe_check_subprocess(code):
  """
  <Purpose>
    Runs safe_check() in a subprocess. This is done because the AST safe_check()
    creates uses a large amount of RAM. By running safe_check() in a subprocess
    we can guarantee that the memory will be reclaimed when the process ends.
  
  <Arguments>
    code: See safe_check.
    
  <Exceptions>
    As with safe_check.
  
  <Return>
    See safe_check.
  """
  
  # Get the path to safe_check.py by using the original start directory of python
  path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR, "safe_check.py")
  
  # Start a safety check process, reading from the user code and outputing to a pipe we can read
  proc = subprocess.Popen([sys.executable, path_to_safe_check],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  
  # Write out the user code, close so the other end gets an EOF
  proc.stdin.write(code)
  proc.stdin.close()
  
  # Wait for the process to terminate
  starttime = nonportable.getruntime()

  # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
  while nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT:
    # Did the process finish running?
    if proc.poll() != None:
      break;
    time.sleep(0.02)
  else:
    # Kill the timed-out process
    try:
      harshexit.portablekill(proc.pid)
    except:
      pass
    raise Exception, "Evaluation of code safety exceeded timeout threshold \
                    ("+str(nonportable.getruntime() - starttime)+" seconds)"
  
  # Read the output and close the pipe
  rawoutput = proc.stdout.read()
  proc.stdout.close()


  # Interim fix for #1080: Get rid of stray debugging output on Android
  # of the form "dlopen libpython2.6.so" and "dlopen /system/lib/libc.so",
  # yet preserve all of the other output (including empty lines).

  if IS_ANDROID:
    output = ""
    for line in rawoutput.split("\n"):
      # Preserve empty lines
      if line == "":
        output += "\n"
        continue
      # Suppress debug messages we know can turn up
      wordlist = line.split()
      if wordlist[0]=="dlopen":
        if wordlist[-1]=="/system/lib/libc.so":
          continue
        if wordlist[-1].startswith("libpython") and \
          wordlist[-1].endswith(".so"):
          # We expect "libpython" + version number + ".so".
          # The version number should be a string convertible to float.
          # If it's not, raise an exception.
          try:
            versionstring = (wordlist[-1].replace("libpython", 
              "")).replace(".so", "")
            junk = float(versionstring)
          except TypeError, ValueError:
            raise Exception("Unexpected debug output '" + line + 
              "' while evaluating code safety!")
      else:
        output += line + "\n"

    # Strip off the last newline character we added
    output = output[0:-1]
Пример #20
0
def do_oddballtests():
  global passcount
  global failcount
  global endput

  # oddball "stop" tests...
  logstream.write("Running test %-50s [" % "Stop Test 1")
  logstream.flush()

  (testout, testerr) = exec_repy_script("stop_testsleep.py", "restrictions.default", {'stop':'nonexist', 'status':'foo'})
  if testout == '' and testerr == '':
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  else:
    failcount = failcount + 1
    endput = endput+"Stop Test 1\noutput or errput! out:"+testout+"err:"+ testerr+"\n\n"
    logstream.write("FAILED]\n")



  # oddball "stop" test2...
  logstream.write("Running test %-50s [" % "Stop Test 2")
  logstream.flush()

  (testout, testerr) = exec_repy_script("stop_testsleep.py", "restrictions.default", {'stop':'repy.py', 'status':'foo'})
  if (not mobileNoSubprocess) and testout == '' and testerr != '':
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  elif mobileNoSubprocess and testout.find('Traceback') == -1:
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  else:
    failcount = failcount + 1
    logstream.write("FAILED]\n")
    endput = endput+"Stop Test 2\noutput or no errput! out:"+testout+"err:"+ testerr+"\n\n"


  # oddball "stop" test3...
  logstream.write("Running test %-50s [" % "Stop Test 3")
  logstream.flush()

  # clean up the stop file if it already exists...
  if os.path.exists('junk_test.out'):
    os.remove('junk_test.out')

  (testout, testerr) = exec_repy_script('stop_testsleepwrite.py', "restrictions.default", {'stop':'junk_test.out','status':'foo'})
  if testout == '' and testerr == '':
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  else:
    failcount = failcount + 1
    logstream.write("FAILED]\n")
    endput = endput+"Stop Test 3\noutput or errput! out:"+testout+"err:"+ testerr+"\n\n"



  # "stop" test3, however with an absolute path to the stop file
  logstream.write("Running test %-50s [" % "Absolute Path Stop Test")
  logstream.flush()

  # clean up the stop file if it already exists...
  if os.path.exists('junk_test.out'):
    os.remove('junk_test.out')

  currentdirectory = os.getcwd()
  stopfilename = os.path.join(currentdirectory,'junk_test.out')
  # This is needed when a space is in the directory where the tests are run
  stopfilename = '"'+stopfilename+'"'

  (testout, testerr) = exec_repy_script('stop_testsleepwrite.py', "restrictions.default", {'stop':stopfilename,'status':'foo'})
  if testout == '' and testerr == '':
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  else:
    failcount = failcount + 1
    logstream.write("FAILED]\n")
    endput = endput+"Absolute Path Stop Test\noutput or errput! out:"+testout+"err:"+ testerr+"\n\n"


  
  # Test running repy from a sub directory
  logstream.write("Running test %-50s [" % "Sub-directory test")
  logstream.flush()
  
  # Make a temporary directory
  if not os.path.exists("subdirtest"):
    os.mkdir("subdirtest")

  (testout, testerr) = exec_repy_script("../n_testinit.py", "../restrictions.default", {'cwd':'subdirtest'})
  if testout != '' and testerr == '':
    passcount = passcount + 1
    logstream.write(" PASS ]\n")
  else:
    failcount = failcount + 1
    endput = endput+"Sub-directory test\nno output or errput! out:"+testout+"err:"+ testerr+"\n\n"
    logstream.write("FAILED]\n")


  # oddball killing the parent test...
  logstream.write("Running test %-50s [" % "Kill Repy resource monitor.")
  logstream.flush()

  # Mac or Linux...
  if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
    # Get the location of python
    locationproc = subprocess.Popen("which python",shell=True,stdout=subprocess.PIPE)
    locationproc.wait()
    location = locationproc.stdout.read().strip()
    locationproc.stdout.close()

    # Start the test
    p =  subprocess.Popen((location+" repy.py restrictions.default killp_writetodisk.py").split(),stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    pid = p.pid

    # give it a few seconds to start...
    time.sleep(4)

    # find the orphaned child's PID...  Different on Mac / Linux because of ps 
    # options...
    if nonportable.ostype == 'Darwin' or nonportable.osrealtype == 'FreeBSD':
      # run ps and print the 1st field (PID) of the line with 2nd field (PPID)
      # equal to the parent pid...
      childpidprocess = subprocess.Popen("ps -aO ppid | awk '{if ($2=="+str(pid)+") {print $1}}'",stdout=subprocess.PIPE, shell=True)
      childpidstring = childpidprocess.stdout.read().strip()
      childpidprocess.stdout.close()

    elif nonportable.ostype == 'Linux':

      # run ps and print the 2nd field (PID) of the line with 3rd field (PPID)
      # equal to the parent pid...
      childpidprocess = subprocess.Popen("ps -ef | awk '{if ($3=="+str(pid)+") {print $2}}'",stdout=subprocess.PIPE, shell=True)
      childpidstring = childpidprocess.stdout.read().strip()
      childpidprocess.stdout.close()

    else: 
      print "Internal Error re-examining OS type '"+nonportable.ostype+"'!"
      sys.exit(1)
      
  # Windows 
  elif nonportable.ostype == 'Windows' or nonportable.ostype == 'WindowsCE':
    # this is much easier because we don't worry about the path or have 
    # children to worry about.
    p = subprocess.Popen("python repy.py restrictions.default killp_writetodisk.py".split(),stdout=subprocess.PIPE,stderr=subprocess.PIPE)

    pid = p.pid
    
    # Wait while the process starts
    time.sleep(4)

  else:
    print "Error: Unknown OS type '"+nonportable.ostype+"'!"
    sys.exit(1)


  
  # Kill the repy resource monitor
  harshexit.portablekill(pid)
  time.sleep(1)
  
  # See ticket #413 and #421
  # This is a workaround for the possibility that the repy child was sleeping
  if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
    # Send SIGCONT to the child if the process still exists, it should wake up,
    # get a read error when checking the pipe, and then exit...
    try: 
      os.kill(int(childpidstring), signal.SIGCONT)
    except OSError:
      # the child has likely exited
      pass

    except ValueError:
      # This happens when the child PID is ''
      pass
      
    # Wait for the signal to take effect
    time.sleep(1)    

  try:
    # Make sure the file size is not changing
    firstsize = os.path.getsize("junk_test.out")
    time.sleep(1)
    secondsize = os.path.getsize("junk_test.out")
  except (OSError, IOError):
    failcount = failcount + 1
    logstream.write("FAILED]\n")
    endput = endput+"Killing Repy's resource monitor did not stop repy (size error)!\n\n"

  else:

    if firstsize == secondsize:
      passcount = passcount + 1
      logstream.write(" PASS ]\n")
    
    else:
      failcount = failcount + 1
      logstream.write("FAILED]\n")
      endput = endput+"Killing Repy's resource monitor did not stop repy!\n\n"

  # Close the pipes
  p.stdout.close()
  p.stderr.close()
  

  # Make sure repy.py works when invoked with options in a various order (to
  # test that adding getopt worked.)
  logstream.write("Running test %-50s [" % "repy.py takes args any order")
  test_process = subprocess.Popen(["python", "repy.py", "--simple", "--logfile", "log.log", "restrictions.loose", "testoptions.py"])
  test_process.wait()
  
  # Check that log was created.
  if os.path.exists("log.log.old"):
    os.remove("log.log.old")
  
    test_process = subprocess.Popen(["python", "repy.py", "--logfile", "log.log", "--simple", "restrictions.loose", "testoptions.py"])
    test_process.wait()
    
    # Check that log was created (again).
    if os.path.exists("log.log.old"):
      passcount += 1
      logstream.write(" PASS ]\n")
      os.remove("log.log.old")
    else:
      failcount += 1
      logstream.write("FAILED]\n")
      endput = endput+"Passing arguments in the opposite order failed!\n\n"
  else:
    failcount += 1
    logstream.write("FAILED]\n")
    endput = endput+"Test for passing arguments in the opposite order failed!\n\n"

  logstream.flush()
Пример #21
0
def safe_check(code):
    """Check the code to be safe."""
    # NOTE: This code will not work in Windows Mobile due to the reliance on subprocess

    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR,
                                      "safe_check.py")

    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen([sys.executable, path_to_safe_check],
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)

    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()

    # Wait for the process to terminate
    starttime = nonportable.getruntime()
    status = None

    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while status == None and (nonportable.getruntime() - starttime <
                              EVALUTATION_TIMEOUT):
        status = proc.poll()
        time.sleep(0.02)

    else:
        # Check if the process is still running
        if status == None:
            # Try to terminate the external process
            try:
                harshexit.portablekill(proc.pid)
            except:
                pass

            # Raise an exception
            raise Exception, "Evaluation of code safety exceeded timeout threshold (" + str(
                nonportable.getruntime() - starttime) + " seconds)"

    # Read the output and close the pipe
    rawoutput = proc.stdout.read()
    proc.stdout.close()

    # Interim fix for #1080: Get rid of stray debugging output on Android
    # of the form "dlopen libpython2.6.so" and "dlopen /system/lib/libc.so",
    # yet preserve all of the other output (including empty lines).

    output = ""
    for line in rawoutput.split("\n"):
        # Preserve empty lines
        if line == "":
            output += "\n"
            continue
        # Suppress debug messages we know can turn up
        wordlist = line.split()
        if wordlist[0] == "dlopen":
            if wordlist[-1] == "/system/lib/libc.so":
                continue
            if wordlist[-1].startswith("libpython") and \
              wordlist[-1].endswith(".so"):
                # We expect "libpython" + version number + ".so".
                # The version number should be a string convertible to float.
                # If it's not, raise an exception.
                try:
                    versionstring = (wordlist[-1].replace("libpython",
                                                          "")).replace(
                                                              ".so", "")
                    junk = float(versionstring)
                except TypeError, ValueError:
                    raise Exception("Unexpected debug output '" + line +
                                    "' while evaluating code safety!")
        else:
            output += line + "\n"
Пример #22
0
    # Wait for the process to terminate
    starttime = nonportable.getruntime()

    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT:
        # Did the process finish running?
        if (IS_ANDROID and os.waitpid(procpid, os.WNOHANG) != (0, 0)) or \
            (not IS_ANDROID and proc.poll() != None):
            break

        time.sleep(0.02)
    else:
        # Kill the timed-out process
        try:
            harshexit.portablekill(procpid)
        except:
            pass
        raise Exception, "Evaluation of code safety exceeded timeout threshold \
                    (" + str(nonportable.getruntime() -
                             starttime) + " seconds)"

    if IS_ANDROID:
        # Should return ("safe_check", "None")
        msg = nonportable.read_message_from_pipe(readhandle)

        if type(msg) == tuple and len(msg) == 2 and msg[0] == "safe_check":
            rawoutput = msg[1]
        else:
            rawoutput = ""
Пример #23
0
# without closing stdin, stdout, stderr, nmmain.py won't execute on XP
nmproc.stdin.close()
nmproc.stdout.close()
nmproc.stderr.close()


try:
  # We'll want to kill this once we are told to do so... (sys.stdin.close() is
  # the signal)
  sys.stdin.read()
except KeyboardInterrupt:
  # the user interrupted us, let's clean up!
  print
  print 'Cleaning up the subprocess'

# We need the PID.   Since the node manager daemonizes, this isn't the pid of
# nmproc.   We can get the PID from the log
nodemanagerlogfo = open('v2'+os.sep+'nodemanager.old')

firstline = nodemanagerlogfo.readline()

# an entry looks like this:
# 1292537407.82:PID-27493:[INFO]: Running nodemanager in test mode
# let's get the PID out as a number...
pidportion = firstline.split(':')[1]
assert(pidportion.startswith('PID-'))
nmpid = int(pidportion[4:])

# let's terminate the node manager...
harshexit.portablekill(nmpid)
Пример #24
0
def do_oddballtests():
    global passcount
    global failcount
    global endput

    # oddball "stop" tests...
    logstream.write("Running test %-50s [" % "Stop Test 1")
    logstream.flush()

    (testout, testerr) = exec_repy_script("stop_testsleep.py",
                                          "restrictions.default", {
                                              'stop': 'nonexist',
                                              'status': 'foo'
                                          })
    if testout == '' and testerr == '':
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    else:
        failcount = failcount + 1
        endput = endput + "Stop Test 1\noutput or errput! out:" + testout + "err:" + testerr + "\n\n"
        logstream.write("FAILED]\n")

    # oddball "stop" test2...
    logstream.write("Running test %-50s [" % "Stop Test 2")
    logstream.flush()

    (testout, testerr) = exec_repy_script("stop_testsleep.py",
                                          "restrictions.default", {
                                              'stop': 'repy.py',
                                              'status': 'foo'
                                          })
    if (not mobileNoSubprocess) and testout == '' and testerr != '':
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    elif mobileNoSubprocess and testout.find('Traceback') == -1:
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    else:
        failcount = failcount + 1
        logstream.write("FAILED]\n")
        endput = endput + "Stop Test 2\noutput or no errput! out:" + testout + "err:" + testerr + "\n\n"

    # oddball "stop" test3...
    logstream.write("Running test %-50s [" % "Stop Test 3")
    logstream.flush()

    # clean up the stop file if it already exists...
    if os.path.exists('junk_test.out'):
        os.remove('junk_test.out')

    (testout, testerr) = exec_repy_script('stop_testsleepwrite.py',
                                          "restrictions.default", {
                                              'stop': 'junk_test.out',
                                              'status': 'foo'
                                          })
    if testout == '' and testerr == '':
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    else:
        failcount = failcount + 1
        logstream.write("FAILED]\n")
        endput = endput + "Stop Test 3\noutput or errput! out:" + testout + "err:" + testerr + "\n\n"

    # "stop" test3, however with an absolute path to the stop file
    logstream.write("Running test %-50s [" % "Absolute Path Stop Test")
    logstream.flush()

    # clean up the stop file if it already exists...
    if os.path.exists('junk_test.out'):
        os.remove('junk_test.out')

    currentdirectory = os.getcwd()
    stopfilename = os.path.join(currentdirectory, 'junk_test.out')
    # This is needed when a space is in the directory where the tests are run
    stopfilename = '"' + stopfilename + '"'

    (testout, testerr) = exec_repy_script('stop_testsleepwrite.py',
                                          "restrictions.default", {
                                              'stop': stopfilename,
                                              'status': 'foo'
                                          })
    if testout == '' and testerr == '':
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    else:
        failcount = failcount + 1
        logstream.write("FAILED]\n")
        endput = endput + "Absolute Path Stop Test\noutput or errput! out:" + testout + "err:" + testerr + "\n\n"

    # Test running repy from a sub directory
    logstream.write("Running test %-50s [" % "Sub-directory test")
    logstream.flush()

    # Make a temporary directory
    if not os.path.exists("subdirtest"):
        os.mkdir("subdirtest")

    (testout, testerr) = exec_repy_script("../n_testinit.py",
                                          "../restrictions.default",
                                          {'cwd': 'subdirtest'})
    if testout != '' and testerr == '':
        passcount = passcount + 1
        logstream.write(" PASS ]\n")
    else:
        failcount = failcount + 1
        endput = endput + "Sub-directory test\nno output or errput! out:" + testout + "err:" + testerr + "\n\n"
        logstream.write("FAILED]\n")

    # oddball killing the parent test...
    logstream.write("Running test %-50s [" % "Kill Repy resource monitor.")
    logstream.flush()

    # Mac or Linux...
    if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
        # Get the location of python
        locationproc = subprocess.Popen("which python",
                                        shell=True,
                                        stdout=subprocess.PIPE)
        locationproc.wait()
        location = locationproc.stdout.read().strip()
        locationproc.stdout.close()

        # Start the test
        p = subprocess.Popen(
            (location +
             " repy.py restrictions.default killp_writetodisk.py").split(),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        pid = p.pid

        # give it a few seconds to start...
        time.sleep(4)

        # find the orphaned child's PID...  Different on Mac / Linux because of ps
        # options...
        if nonportable.ostype == 'Darwin' or nonportable.osrealtype == 'FreeBSD':
            # run ps and print the 1st field (PID) of the line with 2nd field (PPID)
            # equal to the parent pid...
            childpidprocess = subprocess.Popen("ps -aO ppid | awk '{if ($2==" +
                                               str(pid) + ") {print $1}}'",
                                               stdout=subprocess.PIPE,
                                               shell=True)
            childpidstring = childpidprocess.stdout.read().strip()
            childpidprocess.stdout.close()

        elif nonportable.ostype == 'Linux':

            # run ps and print the 2nd field (PID) of the line with 3rd field (PPID)
            # equal to the parent pid...
            childpidprocess = subprocess.Popen("ps -ef | awk '{if ($3==" +
                                               str(pid) + ") {print $2}}'",
                                               stdout=subprocess.PIPE,
                                               shell=True)
            childpidstring = childpidprocess.stdout.read().strip()
            childpidprocess.stdout.close()

        else:
            print "Internal Error re-examining OS type '" + nonportable.ostype + "'!"
            sys.exit(1)

    # Windows
    elif nonportable.ostype == 'Windows' or nonportable.ostype == 'WindowsCE':
        # this is much easier because we don't worry about the path or have
        # children to worry about.
        p = subprocess.Popen(
            "python repy.py restrictions.default killp_writetodisk.py".split(),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)

        pid = p.pid

        # Wait while the process starts
        time.sleep(4)

    else:
        print "Error: Unknown OS type '" + nonportable.ostype + "'!"
        sys.exit(1)

    # Kill the repy resource monitor
    harshexit.portablekill(pid)
    time.sleep(1)

    # See ticket #413 and #421
    # This is a workaround for the possibility that the repy child was sleeping
    if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
        # Send SIGCONT to the child if the process still exists, it should wake up,
        # get a read error when checking the pipe, and then exit...
        try:
            os.kill(int(childpidstring), signal.SIGCONT)
        except OSError:
            # the child has likely exited
            pass

        except ValueError:
            # This happens when the child PID is ''
            pass

        # Wait for the signal to take effect
        time.sleep(1)

    try:
        # Make sure the file size is not changing
        firstsize = os.path.getsize("junk_test.out")
        time.sleep(1)
        secondsize = os.path.getsize("junk_test.out")
    except (OSError, IOError):
        failcount = failcount + 1
        logstream.write("FAILED]\n")
        endput = endput + "Killing Repy's resource monitor did not stop repy (size error)!\n\n"

    else:

        if firstsize == secondsize:
            passcount = passcount + 1
            logstream.write(" PASS ]\n")

        else:
            failcount = failcount + 1
            logstream.write("FAILED]\n")
            endput = endput + "Killing Repy's resource monitor did not stop repy!\n\n"

    # Close the pipes
    p.stdout.close()
    p.stderr.close()

    # Make sure repy.py works when invoked with options in a various order (to
    # test that adding getopt worked.)
    logstream.write("Running test %-50s [" % "repy.py takes args any order")
    test_process = subprocess.Popen([
        "python", "repy.py", "--simple", "--logfile", "log.log",
        "restrictions.loose", "testoptions.py"
    ])
    test_process.wait()

    # Check that log was created.
    if os.path.exists("log.log.old"):
        os.remove("log.log.old")

        test_process = subprocess.Popen([
            "python", "repy.py", "--logfile", "log.log", "--simple",
            "restrictions.loose", "testoptions.py"
        ])
        test_process.wait()

        # Check that log was created (again).
        if os.path.exists("log.log.old"):
            passcount += 1
            logstream.write(" PASS ]\n")
            os.remove("log.log.old")
        else:
            failcount += 1
            logstream.write("FAILED]\n")
            endput = endput + "Passing arguments in the opposite order failed!\n\n"
    else:
        failcount += 1
        logstream.write("FAILED]\n")
        endput = endput + "Test for passing arguments in the opposite order failed!\n\n"

    logstream.flush()
Пример #25
0
                raise e
        else:
            kill_repy = True
            error_msg = repr(
                exp) + " Monitor death! Impolitely killing repy process!"
            monitor_exit_code = 98

    finally:
        if (error_msg):
            print >> sys.stderr, error_msg

        # Repy/Montior proccesses both _exit, so the thread should be stopped anyway
        # nmstatusinterface.stop()

        if (kill_repy):
            harshexit.portablekill(repypid)

        # XXX LP: Is this actually doeing something???
        try:
            statusstorage.write_status("Terminated")
        except:
            pass

        # The monitor process (child) should always exit this way on android
        # because we don't want the child to return back to Java if repy (parent)
        # is not alive anymore, which it should not be at this point
        harshexit.harshexit(monitor_exit_code)


def resource_monitor(repypid, pipe_handle):
    """
Пример #26
0
def main():

    repy_args = [
        sys.executable, 'repy.py', 'restrictions.default',
        'test_killp_writetodisk.py'
    ]

    if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':

        process = subprocess.Popen(repy_args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        pid = process.pid

        # Give it a few seconds to start.
        time.sleep(4)

        # Find the orphaned child's PID.

        # Run <ps> and print the first field (PID) of the line with second
        # field (PPID) equal to the parent pid.
        if nonportable.ostype == 'Darwin' or nonportable.osrealtype == 'FreeBSD':
            command = "ps -aO ppid | awk '{if ($2==" + str(
                pid) + ") {print $1}}'"
        elif nonportable.ostype == 'Linux':
            command = "ps -ef | awk '{if ($3==" + str(pid) + ") {print $2}}'"

        (out, error) = subprocess.Popen(command,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE,
                                        shell=True).communicate()
        child_pid = out.strip()

    # Windows
    elif nonportable.ostype == 'Windows' or nonportable.ostype == 'WindowsCE':
        # This is much easier because we don't worry about the path or have
        # children to worry about.
        process = subprocess.Popen(repy_args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)

        pid = process.pid

        # Wait while the process starts.
        time.sleep(4)

    else:
        print "Error: Unknown OS type '" + nonportable.ostype + "'!"
        sys.exit(1)

    # Kill the repy resource monitor.
    harshexit.portablekill(pid)
    time.sleep(1)

    # See ticket #413 and #421
    # This is a workaround for the possibility that the repy child was sleeping
    if nonportable.ostype == 'Darwin' or nonportable.ostype == 'Linux':
        # Send SIGCONT to the child if the process still exists, it should wake up,
        # get a read error when checking the pipe, and then exit...
        try:
            os.kill(int(child_pid), signal.SIGCONT)
        except OSError:
            pass  # The child has likely exited

        # Wait for the signal to take effect
        time.sleep(1)

    # Make sure the file size is not changing
    firstsize = os.path.getsize("junk_test.out")
    time.sleep(1)
    secondsize = os.path.getsize("junk_test.out")

    if firstsize != secondsize: print 'FAIL'
Пример #27
0
def safe_check(code):
    """Check the code to be safe."""
    # NOTE: This code will not work in Windows Mobile due to the reliance on subprocess
    
    # Get the path to safe_check.py by using the original start directory of python
    path_to_safe_check = os.path.join(repy_constants.REPY_START_DIR, "safe_check.py")
    
    # Start a safety check process, reading from the user code and outputing to a pipe we can read
    proc = subprocess.Popen([sys.executable, path_to_safe_check],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    
    # Write out the user code, close so the other end gets an EOF
    proc.stdin.write(code)
    proc.stdin.close()
    
    # Wait for the process to terminate
    starttime = nonportable.getruntime()
    status = None
    
    # Only wait up to EVALUTATION_TIMEOUT seconds before terminating
    while status == None and (nonportable.getruntime() - starttime < EVALUTATION_TIMEOUT):
      status = proc.poll()
      time.sleep(0.02)
      
    else:
      # Check if the process is still running
      if status == None:
        # Try to terminate the external process
        try:
          harshexit.portablekill(proc.pid)
        except:
          pass
      
        # Raise an exception
        raise Exception, "Evaluation of code safety exceeded timeout threshold ("+str(nonportable.getruntime() - starttime)+" seconds)"
    
    
    # Read the output and close the pipe
    rawoutput = proc.stdout.read()
    proc.stdout.close()

    # Interim fix for #1080: Get rid of stray debugging output on Android
    # of the form "dlopen libpython2.6.so" and "dlopen /system/lib/libc.so",
    # yet preserve all of the other output (including empty lines).

    output = ""
    for line in rawoutput.split("\n"):
      # Preserve empty lines
      if line == "":
        output += "\n"
        continue
      # Suppress debug messages we know can turn up
      wordlist = line.split()
      if wordlist[0]=="dlopen":
        if wordlist[-1]=="/system/lib/libc.so":
          continue
        if wordlist[-1].startswith("libpython") and \
          wordlist[-1].endswith(".so"):
          # We expect "libpython" + version number + ".so".
          # The version number should be a string convertible to float.
          # If it's not, raise an exception.
          try:
            versionstring = (wordlist[-1].replace("libpython", 
              "")).replace(".so", "")
            junk = float(versionstring)
          except TypeError, ValueError:
            raise Exception("Unexpected debug output '" + line + 
              "' while evaluating code safety!")
      else:
        output += line + "\n"