Julia via Python

Julia via Python

by Fabien C. -
Number of replies: 9

Hi,

I'm trying to create a new question type to use Julia language with the following template:

import subprocess
julia_prog = """{{ STUDENT_ANSWER | e('py') }}"""
julia_prog += "\n" + """{{TEST.testcode | e('py')}}"""
with open("prog.jl", "w") as src:
    print(julia_prog, file=src)
output = subprocess.check_output(["julia","prog.jl"], universal_newlines=True)
print(output)

However, when I test a question I get the following error:

***Error***
Traceback (most recent call last):
  File "__tester__.python3", line 11, in <module>
    output = subprocess.check_output(["julia","prog.jl"], universal_newlines=True)
  File "/usr/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.6/subprocess.py", line 403, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.6/subprocess.py", line 709, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: 'julia'

Any idea of what could be wrong?

In reply to Fabien C.

Re: Julia via Python

by Richard Lobb -

I've never used julia so I'm not sure if any special conditions apply to running it. But that particular error would normally mean that the julia program isn't executable by the running task. Jobe tasks run as user jobe00, or jobe01, jobe02 etc. These have minimal privilege, so the julia program would have to be executable by anyone. Have you done chmod a+x /usr/local/bin/julia (or whatever its path is)?

Some other things to try:

  • Use the full path to the julia executable. The sandbox runs in a very restricted environment with a minimal PATH variable - you may not be executing what you expect.
  • Set the memory limit for the question in CodeRunner (on Moodle) to 0 - tasks that run out of memory behave in unpredictable ways, often generating spurious errors.
  • Precede the check_output call with the following two lines (adjusting the second to whatever the expected julia path is) to make sure things are as you expect:
    print(subprocess.check_output('which julia', shell=True, universal_newlines=True))
    print(subprocess.check_output('ls -l /usr/local/bin/julia', shell=True, universal_newlines=True))
  • Make sure that changing the command you're executing from julia to a standard Linux program like gcc doesn't generate the same error. Obviously gcc won't compile the julia program but it should at least run and generate some plausible error messages.

Richard


In reply to Richard Lobb

Re: Julia via Python

by Fabien C. -

Thank you so much Richard for your detailed answer. 

The jobe server is installed in a jobeinabox docker container built with the command docker-compose build and run with the docker command:

sudo docker run -d -p 4000:80 --name jobe trampgeek/jobeinabox:latest


This is what I did until now:

1) I checked the permissions of the julia binary, they seem to be correctly configured: 

-rwxr-xr-x. 1 1337 1337 44080 Jan 22 11:33 julia

2) I use the full path: /usr/local/bin/julia

3) The memory limit is set to 0

4) I added the following lines:

print(subprocess.check_output('echo $(whoami)', shell=True, universal_newlines=True))
print(subprocess.check_output('echo $PATH', shell=True, universal_newlines=True))
print(subprocess.check_output('ls -al /usr/local/bin', shell=True, universal_newlines=True))
print(subprocess.check_output('which julia', shell=True, universal_newlines=True))
print(subprocess.check_output('ls -l /usr/local/bin/julia', shell=True, universal_newlines=True))

When checking the output of the 'which julia' command I get the following error:

subprocess.CalledProcessError: Command 'which julia' returned non-zero exit status 1.
With the command '["/usr/local/bin/julia","prog.jl"] I still get:

PermissionError: [Errno 13] Permission denied: '/usr/local/bin/julia'
For the 4 first commands ('echo $(whoami)', 'echo $PATH', 'ls -al /usr/local/bin' and 'ls -l /usr/local/bin/julia') I get:

jobe00

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

total 0
drwxr-xr-x. 1 root root 55 Mar 31 10:14 .
drwxr-xr-x. 1 root root 17 Mar 8 10:00 ..
lrwxrwxrwx. 1 root root 43 Mar 31 10:14 julia -> /root/packages/julias/julia-1.1.0/bin/julia
lrwxrwxrwx. 1 root root 43 Mar 31 10:14 julia-1.1 -> /root/packages/julias/julia-1.1.0/bin/julia
lrwxrwxrwx. 1 root root 43 Mar 31 10:14 julia-1.1.0 -> /root/packages/julias/julia-1.1.0/bin/julia
lrwxrwxrwx. 1 root root 43 Mar 31 10:14 /usr/local/bin/julia -> /root/packages/julias/julia-1.1.0/bin/julia




In reply to Fabien C.

Re: Julia via Python

by Richard Lobb -

I think it's significant that both which julia and the attempt to execute julia fail, while everything else works. I see that /usr/local/bin/julia is a link to /root/packages/julias/julia-1.1.0/bin/julia and I strongly suspect that jobe00 doesn't have access to all directories in that path. In the distributed jobeinabox, the directory /root has root-only access so that's a blocker for a start, unless you did a chmod on it.

The commands

sudo chgrp -R jobe /root
sudo chmod -R g+rX /root 

should solve that particular problem at least, but I'm a bit reluctant to recommend it. I don't have enough experience with Docker to know what the security implications are. A safer option would probably be to uninstall julia and reinstall it somewhere less locked down. But I don't know anything about julia so can't be more specific.

In reply to Richard Lobb

Re: Julia via Python

by Fabien C. -

Thank again for your help! I reinstalled Julia and checked the permissions. Now the julia command is recognized. For example, the command:

print(subprocess.check_output('julia -v', shell=True, universal_newlines=True))

gives: 

julia version 1.0.3

However, when running whatever program in julia with the same subprocess.check_output() python command gives a segmentation fault:

***Error***
Segmentation fault (core dumped)
Traceback (most recent call last):
  File "__tester__.python3", line 17, in <module>
    print(subprocess.check_output('julia prog.jl', shell=True, universal_newlines=True))
  File "/usr/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.6/subprocess.py", line 418, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'julia prog.jl' returned non-zero exit status 139.

I verified that the prog.jl file has been correctly generated with:

print(subprocess.check_output('cat prog.jl', shell=True, universal_newlines=True))

which returns:

println("Test")
println("Test")

Would you have idea of the origin of this segmentation fault?



In reply to Fabien C.

Re: Julia via Python

by Richard Lobb -

Have you run it with the memory limit set to 0? Segmentation faults are the usual outcome when a program runs out of memory (malloc returns null). You should also try raising the number of processes (parameter numprocs in the sandbox parameters setting) to some silly number (e.g. 200?).  See https://coderunner.org.nz/mod/forum/discuss.php?d=164

I am assuming the same command works fine from the command line within the Jobe sandbox? 

In reply to Richard Lobb

Re: Julia via Python

by Fabien C. -

Yes, the same command works fine from the command line within the Jobe sandbox. I also put {"numprocs": 300} in Advanced customisation > Sandbox > Parameters, and 0 in MemLimit. I still get the same segmentation fault error.

In reply to Fabien C.

Re: Julia via Python

by Richard Lobb -

If a program runs from the command line but not via CodeRunner it's usually because of memory and process limits imposed by the RunGuard sandbox within Jobe. But you've checked both those. It now gets much more problematic. The only other two limitations I can think of are a restricted set of environment variables and the lack of a home directory.

To check the latter, try running the job from the command line as user jobe00:

sudo -u jobe00 julia somefile.jl

If that works then you'll have to go into a more intensive debugging mode. Set the sandbox parameter debug to true, e.g.

{"numprocs": 300, "debug": true}

and run the job again from CodeRunner. From the command line, as root, cd to ~jobe/runs where you should find a folder for each jobe run initiated by the question. The set of files in the folders may give you some ideas. The file prog.cmd is the bash command that runs your job via the RunGuard sandbox. Run that by hand (it should segfault), then try adjusting or removing all the runguard parameters.

If all else fails I can try a julia install myself but you'll have to tell me exactly how you installed julia within jobeinabox. And it won't happen for a few days, I'm afraid - busy time at work now.

Richard

In reply to Richard Lobb

Re: Julia via Python

by Fabien C. -

Dear Richard,

The command:

sudo -u jobe00 julia somefile.jl
works fine, so I went into the debugging mode and noticed the filesize option set to 20000. Obviously I got the same error in prog.err (File size limit exceeded). When changing this value to a bigger one, say, 200000, it runs perfectly! I found that this option corresponds to thedisklimit parameter, so with the parameters set to {"numprocs": 50, "disklimit": 200000} it works flawlessly!

Thank you so much again for you help!

Fabien

In reply to Fabien C.

Re: Julia via Python

by Richard Lobb -

Great to know the problem is solved - well done Fabien!

Richard