Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad error message when missing compiler #2336

Closed
gbruer15 opened this issue Mar 23, 2024 · 5 comments · Fixed by #2340
Closed

Bad error message when missing compiler #2336

gbruer15 opened this issue Mar 23, 2024 · 5 comments · Fixed by #2340

Comments

@gbruer15
Copy link
Contributor

try:
res = run([cc, "--version"], stdout=PIPE, stderr=DEVNULL)
ver = res.stdout.decode("utf-8")
if not ver:
return Version("0")
except UnicodeDecodeError:
return Version("0")
except FileNotFoundError:
if allow_fail:
return Version("0")
else:
error("The `%s` compiler isn't available on this system" % cc)
sys.exit(1)

The reason for catching the FileNotFoundError is likely to print out a nice error message if the compiler command can't be found. But the actual error that is thrown when someone tries to run a nonexistent executable is a permissions error, which is not being caught.

The documentation for subprocess indicates OSError will be thrown in case of missing program. (Search "OSError" on https://docs.python.org/3/library/subprocess.html)

If this makes sense, I can make a pull request to fix it next week.

@mloubout
Copy link
Contributor

Will have a look, thanks. Haven't touch this part in a while so probably right, PR always welcome!

Out of curiosity, what setting triggered this? We never encountered that case.

@gbruer15
Copy link
Contributor Author

I was trying to run on a GPU in a conda environment with Python 3.12.1. I think my issue is I don't have a package for nvc++ installed.

Here's environment variables:

export DEVITO_LANGUAGE=openacc
export DEVITO_ARCH=nvc
export DEVITO_PLATFORM=nvidiaX

export OMP_NUM_TREADS=1
export JULIA_NUM_THREADS=1

Here's the error message that I get when trying to import my Julia package that uses JUDI that uses Devito:

julia> using SeismicPlumeEnsembleFilter
ERROR: InitError: PyError (PyImport_ImportModule) <class 'PermissionError'>
PermissionError(13, 'Permission denied')
  File "/storage/home/hcoda1/4/gbruer3/.julia/packages/JUDI/9qfzJ/src/pysource/models.py", line 4, in <module>
    from devito import (Grid, Function, SubDomain, SubDimension, Eq, Inc,
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/__init__.py", line 123, in <module>
    init_configuration()
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 229, in init_configuration
    configuration.initialize()
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 137, in initialize
    self[k] = v
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 62, in wrapper
    return func(self, key, value)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 53, in wrapper
    return func(self, key, value)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 93, in __setitem__
    self._updated(key, value)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/parameters.py", line 80, in _updated
    retval = self._update_functions[key](value)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/__init__.py", line 53, in <lambda>
    callback=lambda i: compiler_registry[i]())
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/arch/compiler.py", line 534, in __init__
    super(PGICompiler, self).__init__(*args, cpp=True, **kwargs)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/arch/compiler.py", line 203, in __init__
    self.version = sniff_compiler_version(self.CC)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/tools/memoization.py", line 34, in __call__
    value = self.func(*args, **kw)
  File "/storage/home/hcoda1/4/gbruer3/.local/lib/python3.9/site-packages/devito/arch/compiler.py", line 36, in sniff_compiler_version
    res = run([cc, "--version"], stdout=PIPE, stderr=DEVNULL)
  File "/usr/local/pace-apps/spack/packages/linux-rhel7-x86_64/gcc-4.8.5/python-3.9.12-rkxvr6vh25rasj7rrhxd3hpaasuqwcoy/lib/python3.9/subprocess.py", line 505, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/local/pace-apps/spack/packages/linux-rhel7-x86_64/gcc-4.8.5/python-3.9.12-rkxvr6vh25rasj7rrhxd3hpaasuqwcoy/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/pace-apps/spack/packages/linux-rhel7-x86_64/gcc-4.8.5/python-3.9.12-rkxvr6vh25rasj7rrhxd3hpaasuqwcoy/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)

Stacktrace:
  [1] pyimport(name::String)
    @ PyCall ~/.julia/packages/PyCall/1gn3u/src/PyCall.jl:558
  [2] __init__()
    @ JUDI ~/.julia/packages/JUDI/9qfzJ/src/JUDI.jl:169
  [3] _include_from_serialized(pkg::Base.PkgId, path::String, depmods::Vector{Any})
    @ Base ./loading.jl:831
  [4] _tryrequire_from_serialized(modkey::Base.PkgId, path::String, sourcepath::String, depmods::Vector{Any})
    @ Base ./loading.jl:938
  [5] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt64)
    @ Base ./loading.jl:1028
  [6] _require(pkg::Base.PkgId)
    @ Base ./loading.jl:1315
  [7] _require_prelocked(uuidkey::Base.PkgId)
    @ Base ./loading.jl:1200
  [8] macro expansion
    @ ./loading.jl:1180 [inlined]
  [9] macro expansion
    @ ./lock.jl:223 [inlined]
 [10] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:1144
during initialization of module JUDI

@gbruer15
Copy link
Contributor Author

In Python, it at least prints out why command is giving the PermissionError, so it seems like some information is lost when the exception goes through Julia.

>>> import devito
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/__init__.py", line 136, in <module>
    init_configuration()
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/parameters.py", line 222, in init_configuration
    configuration.initialize()
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/parameters.py", line 130, in initialize
    self[k] = v
    ~~~~^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/parameters.py", line 62, in wrapper
    return func(self, key, value)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/parameters.py", line 53, in wrapper
    return func(self, key, value)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/parameters.py", line 84, in __setitem__
    value = self._update_functions[key](value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/__init__.py", line 63, in <lambda>
    callback=lambda i: compiler_registry[i]())
                       ^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/arch/compiler.py", line 576, in __init__
    super().__init__(*args, cpp=True, **kwargs)
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/arch/compiler.py", line 217, in __init__
    self.version = sniff_compiler_version(self.CC)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/tools/memoization.py", line 34, in __call__
    value = self.func(*args, **kw)
            ^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/site-packages/devito/arch/compiler.py", line 37, in sniff_compiler_version
    res = run([cc, "--version"], stdout=PIPE, stderr=DEVNULL)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/subprocess.py", line 548, in run
    with Popen(*popenargs, **kwargs) as process:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/storage/coda1/p-echow7/0/gbruer3/julia/JutulJUDIFilter/SeismicPlumeExperiments/conda-env/lib/python3.12/subprocess.py", line 1953, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: 'nvc++'

@mloubout
Copy link
Contributor

This is quite curious, never seen that before almost looks like it finds nvc++ in some weird path you don't have access to.

More than happy to get the PR to make it more robust.

@gbruer15
Copy link
Contributor Author

gbruer15 commented Mar 24, 2024

Here's more info about how this happens.

The permissions error won't happen if the user has access to every folder. It seems there's some folder in the PATH variable that I don't have access to. When exec or something similar checks each folder in PATH, it encounters an unaccessible location, and that's the error it ends up returning.

https://www.linuxquestions.org/questions/programming-9/execvp-function-behaviour-for-root-vs-user-4175599625/#post5669769

Here's a simple program to show the behavior:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, const char** argv) {
    int rv;
    char * const* args = {NULL};
    rv = execvp("./doesntexist", args);
    if (rv == -1) {
        perror("");
    }
    rv = execvp("doesntexist", args);
    if (rv == -1) {
        perror("");
    }
    return 0;
}

Output:

No such file or directory
Permission denied

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants