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

Resolve OSX error accessing closed filehandle #3467

Merged
merged 3 commits into from
Feb 6, 2025

Conversation

jsiirola
Copy link
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
34 of 35 checks passed
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