Repository: numpy/numpy

Issue:
f2py build hangs after running gcc w/1.15.0
Sorry for a rather incomplete bug report, but isolating this to a code fragment may not be possible. I am happy to provide more help in diagnosis, though. 

I have an automated Jenkins build procedure that uses f2py to generate .so files from a series of Fortran files. With anaconda packages 

    numpy-1.14.5               |   py27h1b885b7_4          35 KB
    numpy-base-1.14.5          |   py27hdbf6ddf_4         4.1 MB

running on VM with Red Hat Enterprise Linux Server release 7.5 (Maipo), my build runs fine. If I update to 

    numpy                     1.15.0           py27h1b885b7_0  
    numpy-base                1.15.0           py27h3dfced4_0  

The build hangs in this command:

```
jenkins  23248 23087  0 12:10 ?        00:00:02 /var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/bin/python /var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/bin/f2py -c fellipse.for -m fellipse libspsubs.a libtexturesubs.a libDIFFaXsubs.a libpowsubs.a --fcompiler=gnu95 --f77exec=gfortran --f77flags=-fno-range-check -m64
```
with this following output:

```
building 'fellipse' extension
compiling C sources
C compiler: gcc -pthread -B /var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC

creating /tmp/tmpnkv0Hd/tmp
creating /tmp/tmpnkv0Hd/tmp/tmpnkv0Hd
creating /tmp/tmpnkv0Hd/tmp/tmpnkv0Hd/src.linux-x86_64-2.7
compile options: '-I/tmp/tmpnkv0Hd/src.linux-x86_64-2.7 -I/var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/lib/python2.7/site-packages/numpy/core/include -I/var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/include/python2.7 -c'
gcc: /tmp/tmpnkv0Hd/src.linux-x86_64-2.7/fellipsemodule.c
gcc: /tmp/tmpnkv0Hd/src.linux-x86_64-2.7/fortranobject.c
```

It apparently completes the gcc step and then hangs. It is not in an infinite loop, since the CPU time is not increasing. This is problem reproducible and restoring the previous numpy version addresses it. 



Discussion:
Any chance you could run a bisection on this? Also, where are you getting numpy in both cases?
I am getting numpy from anaconda. 

Not too sure about how to run a bisection, but let me see if I can get a test together. 
I am running into this, too.  Downgrading to 1.14.5 fixes the issue.
If you can run it locally, you can use [debugging techniques](https://stackoverflow.com/questions/25308847/attaching-a-process-with-pdb) to break into the hung process and get a gdb or pdb command line.
Can you compare the log in 1.15 to a successful one? Are the flags the same?
@mattip I will try to look using GDB later tonight and will update you with what I find.  It's beer time for now.

Here is the output of running the same command using both 1.14.5 and 1.15.0.  Sorry for the long paths.  This is done in a docker instance with weird install paths.

### Command

`f2py --fcompiler=gfortran --opt="-O3" -L. -L/usr/lib  -I. -I/build/dev_geoips/link/geoips/geoips/geoalgs/include -I/usr/include  -m libconfig skip:  : -c config/config.f90 config.h`

### 1.14.5
```
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "libconfig" sources
f2py options: ['skip:', ':']
f2py:> /tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.c
creating /tmp/tmpIySmCL/src.linux-x86_64-2.7
Reading fortran codes...
    Reading file 'config/config.f90' (format:free)
Line #9 in config/config.f90:"    include "config.h""
    readfortrancode: could not find include file 'config.h' in config. Ignoring.
Post-processing...
    Block: libconfig
            Block: config
Post-processing (stage 2)...
    Block: libconfig
        Block: unknown_interface
            Block: config
Building modules...
    Building module "libconfig"...
        Constructing F90 module support for "config"...
          Variables: bin_path lib_path inc_path src_path ancildat_path install_path
    Wrote C/API module "libconfig" to file "/tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.c"
    Fortran 90 wrappers are saved to "/tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90"
  adding '/tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.c' to sources.
  adding '/tmp/tmpIySmCL/src.linux-x86_64-2.7' to include_dirs.
copying /build/usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmpIySmCL/src.linux-x86_64-2.7
copying /build/usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmpIySmCL/src.linux-x86_64-2.7
  adding '/tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90' to sources.
 - nothing done with h_files = ['config.h']
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler using build_ext
building 'libconfig' extension
compiling C sources
C compiler: gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC

creating /tmp/tmpIySmCL/tmp
creating /tmp/tmpIySmCL/tmp/tmpIySmCL
creating /tmp/tmpIySmCL/tmp/tmpIySmCL/src.linux-x86_64-2.7
compile options: '-I. -I/build/dev_geoips/link/geoips/geoips/geoalgs/include -I/usr/include -I/tmp/tmpIySmCL/src.linux-x86_64-2.7 -I/build/usr/local/lib/python2.7/site-packages/numpy/core/include -I/build/usr/local/include/python2.7 -c'
gcc: /tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.c
In file included from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1816:0,
                 from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
                 from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
                 from /tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.h:13,
                 from /tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.c:15:
/build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
 #warning "Using deprecated NumPy API, disable it by " \
  ^
gcc: /tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.c
In file included from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1816:0,
                 from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
                 from /build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
                 from /tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.h:13,
                 from /tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.c:2:
/build/usr/local/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
 #warning "Using deprecated NumPy API, disable it by " \
  ^
compiling Fortran 90 module sources
Fortran f77 compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -fPIC -O3
Fortran f90 compiler: /usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3
Fortran fix compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -Wall -g -fno-second-underscore -fPIC -O3
creating /tmp/tmpIySmCL/config
compile options: '-I. -I/build/dev_geoips/link/geoips/geoips/geoalgs/include -I/usr/include -I/tmp/tmpIySmCL/src.linux-x86_64-2.7 -I/build/usr/local/lib/python2.7/site-packages/numpy/core/include -I/build/usr/local/include/python2.7 -c'
extra options: '-J/tmp/tmpIySmCL/ -I/tmp/tmpIySmCL/'
gfortran:f90: config/config.f90
compiling Fortran sources
Fortran f77 compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -fPIC -O3
Fortran f90 compiler: /usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3
Fortran fix compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -Wall -g -fno-second-underscore -fPIC -O3
compile options: '-I. -I/build/dev_geoips/link/geoips/geoips/geoalgs/include -I/usr/include -I/tmp/tmpIySmCL/src.linux-x86_64-2.7 -I/build/usr/local/lib/python2.7/site-packages/numpy/core/include -I/build/usr/local/include/python2.7 -c'
extra options: '-J/tmp/tmpIySmCL/ -I/tmp/tmpIySmCL/'
gfortran:f90: /tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90
/usr/bin/gfortran -Wall -g -Wall -g -shared /tmp/tmpIySmCL/tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.o /tmp/tmpIySmCL/tmp/tmpIySmCL/src.linux-x86_64-2.7/fortranobject.o /tmp/tmpIySmCL/config/config.o /tmp/tmpIySmCL/tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfig-f2pywrappers2.o -L. -L/usr/lib -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/build/usr/local/lib -lpython2.7 -lgfortran -o ./libconfig.so
Removing build directory /tmp/tmpIySmCL
```
### 1.15.0

```
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "libconfig" sources
f2py options: ['skip:', ':']
f2py:> /tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfigmodule.c
creating /tmp/tmp0aQ2vk/src.linux-x86_64-2.7
Reading fortran codes...
    Reading file 'config/config.f90' (format:free)
Line #9 in config/config.f90:"    include "config.h""
    readfortrancode: could not find include file 'config.h' in config. Ignoring.
Post-processing...
    Block: libconfig
            Block: config
Post-processing (stage 2)...
    Block: libconfig
        Block: unknown_interface
            Block: config
Building modules...
    Building module "libconfig"...
        Constructing F90 module support for "config"...
          Variables: bin_path lib_path inc_path src_path ancildat_path install_path
    Wrote C/API module "libconfig" to file "/tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfigmodule.c"
    Fortran 90 wrappers are saved to "/tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90"
  adding '/tmp/tmp0aQ2vk/src.linux-x86_64-2.7/fortranobject.c' to sources.
  adding '/tmp/tmp0aQ2vk/src.linux-x86_64-2.7' to include_dirs.
copying /build/usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmp0aQ2vk/src.linux-x86_64-2.7
copying /build/usr/local/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmp0aQ2vk/src.linux-x86_64-2.7
  adding '/tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90' to sources.
 - nothing done with h_files = ['config.h']
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler using build_ext
building 'libconfig' extension
compiling C sources
C compiler: gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC

creating /tmp/tmp0aQ2vk/tmp
creating /tmp/tmp0aQ2vk/tmp/tmp0aQ2vk
creating /tmp/tmp0aQ2vk/tmp/tmp0aQ2vk/src.linux-x86_64-2.7
compile options: '-I. -I/build/dev_geoips/link/geoips/geoips/geoalgs/include -I/usr/include -I/tmp/tmp0aQ2vk/src.linux-x86_64-2.7 -I/build/usr/local/lib/python2.7/site-packages/numpy/core/include -I/build/usr/local/include/python2.7 -c'gcc: /tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfigmodule.c
gcc: /tmp/tmp0aQ2vk/src.linux-x86_64-2.7/fortranobject.c
```
something strange - in the second-to-the-last line of your comment, at the end of the 1.15.0 output, there is a `-c'gcc: /tmp/tmp0aQ2vk/src.linux-x86_64-2.7/libconfigmodule.c`. 

In the corresponding line in the 1.14.5 output, the last bit of that line is `-c'`, then the `gcc: /tmp/tmpIySmCL/src.linux-x86_64-2.7/libconfigmodule.c` appears on its own line.

Now how could that happen, and what connection, if any, does it have to the hung ~the~ process?

Edit: english
It looks like this just copied funny and was actually two lines in both.  I've attached the actual output here.

[make_config_1.14.5.txt](https://github.com/numpy/numpy/files/2278519/make_config_1.14.5.txt)
[make_config_1.15.0.txt](https://github.com/numpy/numpy/files/2278520/make_config_1.15.0.txt)

I'll take a quick look at GDB now, though I've never really worked with GDB before and am not much of a C programmer.


I'm struggling to get GDB working, likely because I'm doing this in a docker container.  I'm going to have to get back to this later.
It might be easier to bisect. A short example of failing code would be helpful to the rest of us in finding the source of this problem.
Sorry, what is meant by "bisect"?

I'll put together something simple and see if it also fails.
To "bisect" means making a binary search for the bad commit. See `git bisect --help`.
Okay, so I create a script that will return 0 for version 1.14.5 and will return 1 for version 1.15.0, then build clone the numpy repo and run a bisection between those two versions to find the specific commit that created the bug, correct?  I assume my script would also have to include building numpy?
Scripts can be tricky if you need to clean the repo between builds, which sometimes happens. Checking for a hang can also be tricky. I'd just make a fortran file which is know to hang and do it by hand. You can give a script a shot, but you are likely to spend more time on the script than a manual. Here is an example where I was running the checks in another terminal.
```
  796  git bisect start
  797  git bisect bad
  798  git bisect good maintenance/1.14.x
  799  git clean -xdf > /dev/null && pyinstall
  800  git bisect good
  801  git clean -xdf > /dev/null && pyinstall
  802  git bisect good
  803  git clean -xdf > /dev/null && pyinstall
  804  git bisect good
  805  git clean -xdf > /dev/null && pyinstall
  806  git bisect good
  807  git clean -xdf > /dev/null && pyinstall
  808  git bisect good
  809  git clean -xdf > /dev/null && pyinstall
  810  git bisect good
  811  git clean -xdf > /dev/null && pyinstall
  812  git bisect good
  813  git clean -xdf > /dev/null && pyinstall
  814  git bisect good
  815  git clean -xdf > /dev/null && pyinstall
  816  git bisect good
  817  git clean -xdf > /dev/null && pyinstall
  818  git bisect good
  819  git clean -xdf > /dev/null && pyinstall
  820  git bisect good
  821  git clean -xdf > /dev/null && pyinstall
  822  git bisect bad
  823  git clean -xdf > /dev/null && pyinstall
  824  git bisect bad
  825  git clean -xdf > /dev/null && pyinstall
  826  git bisect good
  827  git clean -xdf > /dev/null && pyinstall
  828  git bisect bad
  829  git clean -xdf > /dev/null && pyinstall
  830  git bisect bad
  831  git clean -xdf > /dev/null && pyinstall
  832  git bisect good
  833  git clean -xdf > /dev/null && pyinstall
  834  git bisect bad
  835  git clean -xdf > /dev/null && pyinstall
  836  git bisect good
  837  git clean -xdf > /dev/null && pyinstall
  838  git bisect bad
  839  git bisect reset
``` 
FYI, this was taking a long time to go through by hand since I have to rebuild numpy for each commit that needs to be tested, so I wrote a script to do the testing and am using `git bisect run`.  It is currently running.  I'll post results when it's complete.
I have done a bit more work on this, but using the anaconda packages (but not using github installs). What I have found is the bin/f2py scripts differ and by copying the 1.14.5 bin/f2py script over to the numpy 1.15.0 dist prevents the hang.  I tried also swapping a number of other numpy files between dists and nothing else made a difference. The f2py files are quite different and I am not sure what the goal behind this change or even how this file is generated, but thankfully they are short: 

==> f2py-bad <==
```
#!/var/lib/jenkins/jobs/Py2_L64_Build-copy/workspace/conda27/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'numpy==1.15.0','console_scripts','f2py'
__requires__ = 'numpy==1.15.0'
import re
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('numpy==1.15.0', 'console_scripts', 'f2py')()
    )

```
==> f2py-good <==
```
#!/var/lib/jenkins/jobs/Py2_L64_Build/workspace/conda27/bin/python
# See http://cens.ioc.ee/projects/f2py2e/
from __future__ import division, print_function

import os
import sys
for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]:
    try:
        i = sys.argv.index("--" + mode)
        del sys.argv[i]
        break
    except ValueError:
        pass
os.environ["NO_SCIPY_IMPORT"] = "f2py"
if mode == "g3-numpy":
    sys.stderr.write("G3 f2py support is not implemented, yet.\\n")
    sys.exit(1)
elif mode == "2e-numeric":
    from f2py2e import main
elif mode == "2e-numarray":
    sys.argv.append("-DNUMARRAY")
    from f2py2e import main
elif mode == "2e-numpy":
    from numpy.f2py import main
else:
    sys.stderr.write("Unknown mode: " + repr(mode) + "\\n")
    sys.exit(1)
main()

```
The bad script is not in NumPy, it seems to be a Conda addition. You should open an issue with them.
I am not using Conda.  I have installed Python from source and am failing when using numpy both from pip and built from source.

I had a bug in my bisection code.  I'm rerunning now with a more simple test.  It should be done in an hour.
@jsolbrig what is run on your system when you execute the f2py command (unix: which f2py; win: where f2py)? 
It's the f2py installed by running `python setup.py install --user` for numpy.  

> $ which f2py
> ~/.local/bin/f2py
@jsolbrig  Does the contents of that file match what I have above? If so, then I presume this means that this script is generated by the setup.py installation rather than being an anaconda addition. 
This is what my PIP installed versions look like.  I will look at the ones built from source as soon as my bisect is done.  Note, the bad version (1.15.0) has a different shebang and does not use `load_entry_point`, but otherwise is the same.  The working version (1.14.5) is exactly the same other than the shebang.

**Failing version 1.15.0**
```
#!/usr/local/bin/python

# -*- coding: utf-8 -*-
import re
import sys

from numpy.f2py.__main__ import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())
```

**Working version 1.14.5**
```
#!/usr/local/bin/python
# See http://cens.ioc.ee/projects/f2py2e/
from __future__ import division, print_function

import os
import sys
for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]:
    try:
        i = sys.argv.index("--" + mode)
        del sys.argv[i]
        break
    except ValueError:
        pass
os.environ["NO_SCIPY_IMPORT"] = "f2py"
if mode == "g3-numpy":
    sys.stderr.write("G3 f2py support is not implemented, yet.\\n")
    sys.exit(1)
elif mode == "2e-numeric":
    from f2py2e import main
elif mode == "2e-numarray":
    sys.argv.append("-DNUMARRAY")
    from f2py2e import main
elif mode == "2e-numpy":
    from numpy.f2py import main
else:
    sys.stderr.write("Unknown mode: " + repr(mode) + "\\n")
    sys.exit(1)
main()
```
The offending commit appears to be bb7b12672fe7b68c7776a7f757741d4632001bf3 according to the bisect, which appears to be correct.

```
bb7b12672fe7b68c7776a7f757741d4632001bf3 is the first bad commit
commit bb7b12672fe7b68c7776a7f757741d4632001bf3
Author: xoviat <xoviat@users.noreply.github.com>
Date:   Tue Jan 30 17:25:12 2018 -0600

    ENH: Add entry_points for f2py, conv_template, and from_template. (#10463)
    
    * Add entry points for f2py and conv-template
    
    * Add main function to conv_template
    
    * Extract function
    
    * Add entry point

:040000 040000 f44fe4badf57c65e33b8216254f649131d4741b9 10e8407608134965c7c9f7314d6a003aa6dca4a1 M	numpy
:100755 100755 2a04a07e4baea6d83926f97fff23599e0e8e1c89 eb172bf2bfd30cba9c4af6d79cb8bf6b1dbd42e2 M	setup.py
bisect run success
```

Here is what I used for the bisect (config.h probably wasn't needed, but emulates what I started with):

**test_build**
```
#!/bin/env python

from __future__ import print_function

import os
import time
from subprocess import Popen, PIPE


class MakeError(Exception):
    pass


if __name__ == '__main__':
    print('Building numpy')
    os.chdir('{}/numpy'.format(os.getenv('HOME')))
    setup_proc = Popen('git clean -xdf > /dev/null && python setup.py install --user',
                       shell=True, stdout=PIPE, stderr=PIPE)
    stdout, stderr = setup_proc.communicate()
    if setup_proc.returncode:
        raise MakeError('NumPy build failed:\n\tstdout\n{}\n\n\tstderr:\n{}'.format(stdout, stderr))
    else:
        print('Successfully built numpy')

    print('Starting config build')

    DIR = os.path.join(os.getenv('HOME'), 'test_numpy')
    os.chdir(DIR)

    if os.path.isfile('libconfig.so'):
        print('Cleaning up previous make')
        os.unlink('libconfig.so')
    # clean_proc = Popen('make clean; rm -rf lib || true; rm __init__.py || true',
    #                    shell=True, stdout=PIPE, stderr=PIPE)
    # stdout, stderr = clean_proc.communicate()
    # if clean_proc.returncode:
    #     raise MakeError('Failed to clean properly:\n\tstdout\n{}\n\n\tstderr:\n{}'.format(stdout, stderr))
    # else:
    #     print('Successfully cleaned')

    print('Attepmting to build config')
    make_proc = Popen('f2py --fcompiler=gfortran --opt="-O3" -L. -I. -m libconfig skip: : -c config.f90 config.h',
                      shell=True, stdout=PIPE, stderr=PIPE)
    elapsed = 0
    while make_proc.poll() is None:
        time.sleep(0.5)
        elapsed += 0.5
        if elapsed > 5:
            make_proc.terminate()

    stdout, stderr = make_proc.communicate()
    if make_proc.returncode:
        raise MakeError('Failed to build config:\n\tstdout\n{}\n\n\tstderr:\n{}'.format(stdout, stderr))
    else:
        print('Built config successfully')
```

**config.f90**
```
module config

    implicit none

    include "config.h"

    !f2py character(len=256) :: test

end module config
```

**config.h**
```
character(len=256), parameter :: test = "/test"
```

To run the bisect I did:
> $ git bisect start remotes/origin/maintenance/1.15.x remotes/origin/maintenance/1.14.x
> $ git bisect run ~/test_numpy/test_build

A failed result hung and looked like this:
```
Bisecting: 9 revisions left to test after this (roughly 3 steps)
[bb7b12672fe7b68c7776a7f757741d4632001bf3] ENH: Add entry_points for f2py, conv_template, and from_template. (#10463)
running /home/geoips_dev/test_numpy/test_make
Building numpy
Successfully built numpy
Starting config build
Cleaning up previous make
Attepmting to build config
Traceback (most recent call last):
  File "/home/geoips_dev/test_numpy/test_make", line 53, in <module>
    raise MakeError('Failed to build config:\n\tstdout\n{}\n\n\tstderr:\n{}'.format(stdout, stderr))
__main__.MakeError: Failed to build config:
	stdout
Unknown vendor: "gfortran"
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "libconfig" sources
f2py options: ['skip:', ':']
f2py:> /tmp/tmp9vpuX_/src.linux-x86_64-2.7/libconfigmodule.c
creating /tmp/tmp9vpuX_/src.linux-x86_64-2.7
Reading fortran codes...
	Reading file 'config.f90' (format:free)
	Reading file 'config.h' (format:fix)
Post-processing...
	Block: libconfig
			Block: config
Post-processing (stage 2)...
	Block: libconfig
		Block: unknown_interface
			Block: config
Building modules...
	Building module "libconfig"...
		Constructing F90 module support for "config"...
		  Variables: test
	Wrote C/API module "libconfig" to file "/tmp/tmp9vpuX_/src.linux-x86_64-2.7/libconfigmodule.c"
	Fortran 90 wrappers are saved to "/tmp/tmp9vpuX_/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90"
  adding '/tmp/tmp9vpuX_/src.linux-x86_64-2.7/fortranobject.c' to sources.
  adding '/tmp/tmp9vpuX_/src.linux-x86_64-2.7' to include_dirs.
copying /home/geoips_dev/.local/lib/python2.7/site-packages/numpy-1.15.0.dev0+bb7b126-py2.7-linux-x86_64.egg/numpy/f2py/src/fortranobject.c -> /tmp/tmp9vpuX_/src.linux-x86_64-2.7
copying /home/geoips_dev/.local/lib/python2.7/site-packages/numpy-1.15.0.dev0+bb7b126-py2.7-linux-x86_64.egg/numpy/f2py/src/fortranobject.h -> /tmp/tmp9vpuX_/src.linux-x86_64-2.7
  adding '/tmp/tmp9vpuX_/src.linux-x86_64-2.7/libconfig-f2pywrappers2.f90' to sources.
 - nothing done with h_files = ['config.h']
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler using build_ext
building 'libconfig' extension
compiling C sources
C compiler: gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC

creating /tmp/tmp9vpuX_/tmp
creating /tmp/tmp9vpuX_/tmp/tmp9vpuX_
creating /tmp/tmp9vpuX_/tmp/tmp9vpuX_/src.linux-x86_64-2.7
compile options: '-I. -I/tmp/tmp9vpuX_/src.linux-x86_64-2.7 -I/home/geoips_dev/.local/lib/python2.7/site-packages/numpy-1.15.0.dev0+bb7b126-py2.7-linux-x86_64.egg/numpy/core/include -I/build/usr/local/include/python2.7 -c'
gcc: /tmp/tmp9vpuX_/src.linux-x86_64-2.7/libconfigmodule.c
gcc: /tmp/tmp9vpuX_/src.linux-x86_64-2.7/fortranobject.c
```


Here is `f2py` when built from source for version 1.15.1.dev0.  Note that unlike the version I got from PIP it **does** contain `load_entry_point`.

```
#!/build/usr/local/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'numpy==1.15.1.dev0+ada1680','console_scripts','f2py'
__requires__ = 'numpy==1.15.1.dev0+ada1680'
import re
import sys 
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(
        load_entry_point('numpy==1.15.1.dev0+ada1680', 'console_scripts', 'f2py')()
    )  
```
@jsolbrig Great! Thanks for tracking that down. Now we need a fix... :)
@charris I think I have the fix.  All that is needed is to comment out this line in `setup.py`:

> 'f2py = numpy.f2py.__main__:main',

I'm still learning some about `setup.py`.  I'm not sure why this line was added.

Anyway, should I do a pull request?
I know little about this part of things, maybe @pv or @eric-wieser has some thoughts.
for reference, pr #10463 
I'm more confused by this the more I look at it.  Commenting out the line `f2py = numpy.f2py.main:main` should mean that f2py does not get installed to the bin directory, however, after commenting it out the f2py script still gets installed.  Without  directing f2py to be installed with either `script` or `entry_points` I don't understand what would cause it to still be installed.
I'll ping @rgommers too, as he commented on the problem PR.
> I'll ping @rgommers too, as he commented on the problem PR.

Sorry no time for this (or much else) for the rest of August. 

Don't mess with things in `distutils` and `f2py` unless they're obviously broken is a rule we apparently should use more often ....
So, I suppose one easy fix is to revert the PR, but it would be nice to know why it fails.
> I don't understand what would cause it to still be installed.

Hmm, maybe we have dueling processes.
Hmm, I think the script is added in `numpy/f2py/setup.py`
```
    def generate_f2py_py(build_dir):
        f2py_exe = 'f2py' + os.path.basename(sys.executable)[6:]
        if f2py_exe[-4:] == '.exe':
            f2py_exe = f2py_exe[:-4] + '.py'
        if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
            f2py_exe = f2py_exe + '.py'
        target = os.path.join(build_dir, f2py_exe)
        if newer(__file__, target):
            log.info('Creating %s', target)
            f = open(target, 'w')
            f.write(_get_f2py_shebang() + '\n')
            mainloc = os.path.join(os.path.dirname(__file__), "__main__.py")
            with open(mainloc) as mf:
                f.write(mf.read())
            f.close()
        return target

    config.add_scripts(generate_f2py_py)
```
So, the script `f2py.py` is generated as a script during install. I wonder what would happen if you removed that whole bit? Maybe add the shebang to the `__main__.py` file.
Also looks like the last line in `__main__.py` should be replaced by
```
if __name__ == "__main__":
    main()
```
Also, the shebang line is adjusted to match the python version and build command. Hmm, I'm thinking
that for 1.15.1 we should just comment out the line that you have suggested.

For 1.16 we might look to only generate the script and modify the `console_script` to point to it. Note that the script name is currently `f2py` or `f2py3` plus variations with minor versions that seem to be generated by distutils. I'm really not clear how all that is supposed to go down, but don't want to spend a lot of time on it for 1.15.
So, the executable file in 1.15.0 is a generated wrapper. I think it is pointing to the wrong file, it should probably be pointing to `numpy/f2py/f2py2e.py`, which could use re-enabling the `if __main__ == "__name__":` bit. The other script install code should be removed. Don't know if that will work, but I like the idea of leaving the wrapper to the setuptools.
@jsolbrig I put some changes up at #11712 that seem to work, can you give it a shot?
Hmm, that only generates the one wrapper `f2py` with no regard to python version, seems like a bad idea. The other `console_scripts` should probably not be installed.
So the `console_script` names in `setup.py` need to be made version dependent.

EDIT: Previously the `f2py` was appended with the python name extension, i.e., if installed with `python3`, `f2py3` was installed, if installed with `python2.7`, `f2py2.7` was installed. So there can be very stale versions floating about depending on how the install was done.

EDIT: That may explain why there can be problems finding f2py.
I'm coming to the conclusion that `console_scripts` are a very bad idea. @matthew-brett Thoughts?
Chuck - sorry - I don't use `console_scripts` myself - so I don't have a background to give a fast opinion.   Any chance of a summary of what's going on here?
@matthew-brett Ah, I saw a posting of yours somewhere about scripts with an expressed preference for *not* using `console_scripts`, maybe I was mistaken.

I any case, the problem here was apparently related to using `console_scripts` to install the `f2py` script into a bin (or windows equivalent) folder. As it turns out, the `f2py/setup.py` script also had code that did that using distutils `scripts` that was not removed, so the two may have been in conflict. There is also to possibility that the `console_scripts` addition was pointing to an inappropriate file. #11712 fixes those problems and works for me locally but installs `f2py` somewhere differently on windows, so the script tests are failing on that platform.

Why use `console_scripts` in the first place? The argument seems to be that the shebang that works on unix and linux does not work on windows and `console_scripts` deals with that problem. Note that PiP supports a version of this, https://packaging.python.org/specifications/entry-points/, which I am looking at now, and seems to be done a bit differently. The original idea comes from setuptools, which is still mixed into NumPy distutils. I am not clear on all the interactions here, python packaging is still a mess, but ideally I think using entry points looks like a good idea to me in the long term, we just need to figure it out. For the moment I'm inclined to just remove our first shot at adding that capability and revisiting the issue later.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -368,13 +368,6 @@ def setup_package():
         cmdclass={"sdist": sdist_checked},
         python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*',
         zip_safe=False,
-        entry_points={
-            'console_scripts': [
-                'f2py = numpy.f2py.__main__:main',
-                'conv-template = numpy.distutils.conv_template:main',
-                'from-template = numpy.distutils.from_template:main',
-            ]
-        },
     )
 
     if "--force" in sys.argv:


Test patch: