Search code examples
pythondjangosicstus-prolog

OS system call to Sicstus hangs indefinitely using Python


I'm trying to write a proofchecking application that receives proofs from a user on a website and sends it through to a Prolog script to check its validity.

I'm using Django, Python 2.7 and Sicstus. In my server "view.py" file, I call a python script "checkProof.py", passing it the raw text form of the proof the user submits. Inside of that file I have the following function:

def checkProof(pFile, fFile):
    p = subprocess.Popen(['/bin/bash', '-i', '-c', 'sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)],
        stdout=subprocess.PIPE)
    p.communicate() # Hangs here.

proofChecker.pl receives a modified version of the proof (pFile), analyses it and outputs feedback into a feedback file (fFile). The Python script loops until the feedback file is generated, and returns this to the rest of the server.

The first time I call this function, everything works fine and I get the expected output. The second time I call this function, the program hangs indefinitely at "p.communicate()".

This means that, currently, only one proof can be checked using the application between server restarts. The server should be able to check an indefinite number of proofs between restarts.

Does anyone know why this is happening? I'd be happy to include additional information if necessary.

Update

Based on advice given below, I tried three different kinds of calls to try to determine where the problem lies. The first is what I'm trying to do already - calling Sicstus on my real proofchecking code. The second was calling a very simple Prolog script that writes a hardcoded output. The third was a simple Python script that does the same:

def checkProof(pFile, fFile):
  cmd1 = 'sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)
  cmd2 = 'sicstus -l ProofServer/server/tempFeedback.pl -- %s %s' % (pFile, fFile)
  cmd3 = 'python ProofServer/server/tempFeedback.py %s %s' % (pFile, fFile)
  p = subprocess.Popen(['/bin/bash', '-i', '-c', cmd3],
      stdout=subprocess.PIPE)
  p.communicate() # Hangs here.

In all three cases, the application continues to hang on the second attempted call. This implies that the problem is not with calling Sicstus, but just with the way I'm calling programs in general. This is a bit reassuring but I'm still not sure what I'm doing wrong.


Solution

  • I managed to fix this issue, eventually.

    I think the issue was that appending the -i (interactive) flag to bash meant that it expected input, and when it didn't get that input it suspended the process on the second call. This is what was happening when trying to replicate the process with something simpler.

    I got rid of the -i flag, and found that it now raised the error "/bin/bash: sicstus: command not found", even though sicstus is on my server's PATH and I can call it fine if I ssh into the server and call it directly. I fixed this by specifying the full path. I can now check proofs an indefinite number of times between server restarts, which is great. My code is now:

    def checkProof(pFile, fFile):
      cmd = '/usr/local/sicstus4.2.3/bin/sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)
      p = subprocess.Popen(['/bin/bash', '-c', cmd])
      p.communicate()