Skip to content

Resolve OSX error accessing closed filehandle#3467

Merged
blnicho merged 3 commits intoPyomo:mainfrom
jsiirola:osx-closed-filehandle
Feb 6, 2025
Merged

Resolve OSX error accessing closed filehandle#3467
blnicho merged 3 commits intoPyomo:mainfrom
jsiirola:osx-closed-filehandle

Conversation

@jsiirola
Copy link
Copy Markdown
Member

@jsiirola jsiirola commented Feb 5, 2025

Fixes # .

Summary/Motivation:

This is an attempt to resolve an intermittent test failure on OSX (e.g., https://github.com/Pyomo/pyomo/actions/runs/13150779298/job/36697758470?pr=3465) where redirecting the OS file handles (1 & 2) causes an exception accessing a closed file handle.

Note: reviews are appreciated, but please do not merge until we have a chance to run the GHA OSX tests several times to see if this does in fact resolve the intermittent test failure.

Original test failure:

____________________ TestSolvers.test_fixed_vars_3_0_gurobi ____________________

a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_fixed_vars_3_0_gurobi>,)
kw = {}

    @wraps(func)
    def standalone_func(*a, **kw):
>       return func(*(a + p.args), **p.kwargs, **kw)

/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/parameterized/parameterized.py:620: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyomo/contrib/solver/tests/solvers/test_solvers.py:751: in test_fixed_vars_3
    if not opt.available():
pyomo/contrib/solver/gurobi.py:268: in available
    return self._check_license()
pyomo/contrib/solver/gurobi.py:275: in _check_license
    with capture_output(capture_fd=True):
pyomo/common/tee.py:239: in __enter__
    self.fd_redirect[1].__enter__()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyomo.common.tee.redirect_fd object at 0x147c57da0>

    def __enter__(self):
        if self.std:
            # important: flush the current file buffer when redirecting
            getattr(sys, self.std).flush()
            self.original_file = getattr(sys, self.std)
        # Duplicate the original standard file descriptor(file
        # descriptor 1 or 2) to a different file descriptor number
        self.original_fd = os.dup(self.fd)
    
        # Open a file descriptor pointing to the new file
        if isinstance(self.target, int):
            out_fd = self.target
        else:
            out_fd = os.open(self.target, os.O_WRONLY)
    
        # Duplicate the file descriptor for the opened file, closing and
        # overwriting the value for stdout (file descriptor 1).  Only
        # make the new FD inheritable if it is stdout/stderr
        os.dup2(out_fd, self.fd, inheritable=bool(self.std))
    
        # We no longer need this original file descriptor
        if out_fd is not self.target:
            os.close(out_fd)
    
        if self.std:
            if self.synchronize:
                # Cause Python's stdout to point to our new file
                fd = self.fd
            else:
                # IF we are not synchronizing the std file object with
                # the redirected file descriptor, and IF the current
                # file object is pointing to the original file
                # descriptor that we just redirected, then we want to
                # retarget the std file to the original (duplicated)
                # target file descriptor.  This allows, e.g. Python to
                # still write to stdout when we redirect fd=1 to
                # /dev/null
                try:
>                   old_std_fd = getattr(sys, self.std).fileno()
E                   ValueError: I/O operation on closed file

pyomo/common/tee.py:155: ValueError

Changes proposed in this PR:

  • Use the same logic for closing a file handle that we used for determining if we needed to open it.

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

@blnicho blnicho merged commit e5d2c78 into Pyomo:main Feb 6, 2025
29 of 30 checks passed
@jsiirola jsiirola deleted the osx-closed-filehandle branch March 24, 2025 19:52
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 this pull request may close these issues.

3 participants