Repository: mesonbuild/meson

Issue:
difficult error to debug if ninja can't be found
I updated ninja but forgot to `chmod +x` it and got this error. At first I had no clue what was happening until I remembered I updated `ninja`.

```
python3 ./ECS/meson/meson.py --prefix=/home/gitlab-runner/builds/15268147/0/dist-ecs --buildtype=debugoptimized build
Traceback (most recent call last):
  File "/home/gitlab-runner/builds/15268147/0/ECS/meson/mesonbuild/mesonmain.py", line 283, in run
    app.generate()
  File "/home/gitlab-runner/builds/15268147/0/ECS/meson/mesonbuild/mesonmain.py", line 173, in generate
    g.generate(intr)
  File "/home/gitlab-runner/builds/15268147/0/ECS/meson/mesonbuild/backend/ninjabackend.py", line 203, in generate
    self.generate_ending(outfile)
  File "/home/gitlab-runner/builds/15268147/0/ECS/meson/mesonbuild/backend/ninjabackend.py", line 2094, in generate_ending
    ninja_command = environment.detect_ninja()
  File "/home/gitlab-runner/builds/15268147/0/ECS/meson/mesonbuild/environment.py", line 51, in detect_ninja
    p = subprocess.Popen([n, '--version'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
  File "/usr/local/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/local/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
PermissionError: [Errno 13] Permission denied
```


Discussion:
Interesting that `subprocess.Popen` returns a `PermissionError` instead of a `FileNotFoundError` if there's a file in `PATH` with the correct name but no executable bit. Nothing else does this.

Resolving patch:
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -233,7 +233,7 @@ def check_pkgconfig(self):
                              '(%s)' % out.decode().strip())
                 PkgConfigDependency.pkgconfig_found = True
                 return
-        except Exception:
+        except (FileNotFoundError, PermissionError):
             pass
         PkgConfigDependency.pkgconfig_found = False
         if not self.silent:
@@ -358,7 +358,7 @@ def check_wxconfig(self):
                     self.wxc = wxc
                     WxDependency.wx_found = True
                     return
-            except Exception:
+            except (FileNotFoundError, PermissionError):
                 pass
         WxDependency.wxconfig_found = False
         mlog.log('Found wx-config:', mlog.red('NO'))
@@ -1040,7 +1040,7 @@ def detect(self):
             gp = subprocess.Popen([confprog, '--help'],
                                   stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             gp.communicate()
-        except FileNotFoundError:
+        except (FileNotFoundError, PermissionError):
             self.args = None
             mlog.log('Dependency GnuStep found:', mlog.red('NO'), '(no gnustep-config)')
             return
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -43,7 +43,8 @@ def detect_ninja():
     for n in ['ninja', 'ninja-build']:
         try:
             p = subprocess.Popen([n, '--version'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
-        except FileNotFoundError:
+        except (FileNotFoundError, PermissionError):
+            # Doesn't exist in PATH or isn't executable
             continue
         version = p.communicate()[0].decode(errors='ignore')
         # Perhaps we should add a way for the caller to know the failure mode


Test patch: