devitocodes / devito

DSL and compiler framework for automated finite-differences and stencil computation
http://www.devitoproject.org
MIT License
537 stars 221 forks source link

Bad error message when missing compiler #2336

Closed gbruer15 closed 2 months ago

gbruer15 commented 3 months ago

https://github.com/devitocodes/devito/blob/fe47e96197253de924cd338e8569504442f22e56/devito/arch/compiler.py#L38-L50

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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