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

Issue closing down instance on Windows #16

Open
adelosa opened this issue Oct 23, 2016 · 9 comments
Open

Issue closing down instance on Windows #16

adelosa opened this issue Oct 23, 2016 · 9 comments

Comments

@adelosa
Copy link
Contributor

adelosa commented Oct 23, 2016

I'm working with Python 3.5.2 on WIndows 10.
Code like the following:

if __name__ == '__main__':
    with testing.postgresql.Postgresql() as postgresql:
        print("url={}".format(postgresql.url()))
        print("data directory={}".format(postgresql.get_data_directory()))
        run(postgresql.url())

run does nothing..

Receiving the following error:

Traceback (most recent call last):
  File "C:/Users/adelo/IdeaProjects/pr_data/test_orm.py", line 66, in <module>
    run(postgresql.url())
  File "C:\Users\adelo\venv\paymentrouter\lib\site-packages\testing\common\database.py", line 257, in __exit__
url=postgresql://[email protected]:57380/test
data directory=C:\Users\adelo\AppData\Local\Temp\tmpbnndk7ie\data
    self.stop()
  File "C:\Users\adelo\venv\paymentrouter\lib\site-packages\testing\common\database.py", line 197, in stop
    self.terminate(_signal)
  File "C:\Users\adelo\venv\paymentrouter\lib\site-packages\testing\postgresql.py", line 116, in terminate
    super(Postgresql, self).terminate(signal.SIGINT)
  File "C:\Users\adelo\venv\paymentrouter\lib\site-packages\testing\common\database.py", line 212, in terminate
    self.child_process.send_signal(_signal)
  File "c:\users\adelo\appdata\local\programs\python\python35-32\Lib\subprocess.py", line 1351, in send_signal
    raise ValueError("Unsupported signal: {}".format(sig))
ValueError: Unsupported signal: 2
ERROR: testing.common.database: failed to shutdown the server automatically.
Any server processes and files might have been leaked. Please remove them and call the stop() certainly
Process finished with exit code 1

So its saying that signal.SIGINT is not supported.. is that a Windows thing??

adelosa added a commit to adelosa/testing.postgresql that referenced this issue Oct 24, 2016
* Assumes all other platforms work with sigint instead of sigterm
* testcases are broken on Windows due to use of os.fork
@psiofxt
Copy link

psiofxt commented Jan 31, 2018

Hi, I'm unable to get this to work still with the latest testing.postgresql build. Getting unsupported signal 2 still, is this fixed?

@jluttine
Copy link

jluttine commented Jun 6, 2018

I'm still getting this error on Windows with version 1.3.0. Any ideas?

@jluttine
Copy link

jluttine commented Jun 6, 2018

Using the master branch fixes the issue for me. 👍

@danielsaaf
Copy link

Yes, master branch works for me as well! Would be great if the pypi version could be updated to include the windows-fix!

@tuckeryatesjvion
Copy link

Is there any danger in killing the process manually on windows instead of using postgresql.stop()? I rather use the pypi version if possible.

if platform.system() == 'Windows':
  os.system("taskkill /f /pid " + str(postgresql.server_pid))
else:
  postgresql.stop()

@rubenflamshepherd
Copy link

rubenflamshepherd commented Jan 13, 2019

To chime in as well, I had the same issue as above and cloning from the master branch in the repo via pip install git+https://github.com/tk0miya/testing.postgresql.git also fixed it for me.

Would be nice to get this fix into the PyPI version!

EDIT - add the -e flag and subsequent pip freeze > requirements.txt to update your virtualenv appropriately (if you are using one; you should be!).

The full command is
pip install -e git+https://github.com/tk0miya/testing.postgresql.git#egg=testing.postgresql

@mbrameld
Copy link

mbrameld commented Apr 2, 2020

@tk0miya How can we get this fix into PyPi?

@adelosa
Copy link
Contributor Author

adelosa commented Apr 13, 2020

Just FYI, I have long since given up on this module. I was happy to remove this as it was adding a lot of overhead (read time) to my tests, especially on Windows.
I just created my own testcase subclass that creates and destroys the database schema for each test.
It assumes an empty database and specific connection string for the purpose of testing. To me, this is not a massive impact for the speed increases. It also has the benefit of allowing me to dynamically change the database type based on an envvar.. I can now run the same tests against different database types with no code changes.
See https://gist.github.com/adelosa/a2293f2130ceb00a12d17a9c08114c0f if your are interested in the approach. Have posted by testcase subclass. Any questions, comment on the gist.

@zackees
Copy link

zackees commented Sep 27, 2023

What's going on is that the process termination signal being used to call stop() is always 2. Yes, the top level api function allows you to specify the signal int value, but this is ignored in the call chain deep down. In Windows you always get int val 2, no matter what you pass in.

The hack-workaround is to monkey patch signal.SIGINT = signal.SIGTERM for the scope of stop. This is only necessary in windows. Then to clean up you restore the signal.SIGINT back to what it was. This is my fix that's being used for a production app:

db_test_env.py

# pylint: disable=global-statement

import atexit
import os
import platform
import signal
from threading import Lock

import testing.postgresql

_IS_WINDOWS = platform.system() == "Windows"
_INITIALIZED = False
_LOCK = Lock()


def _db_test_env_teardown(postgresql: testing.postgresql.Postgresql) -> None:
    """Clears test database."""
    global _INITIALIZED
    with _LOCK:
        assert _INITIALIZED
        prev_sig_int = signal.SIGINT
        try:
            if _IS_WINDOWS:
                # Hack for windows. Int signal is always 2 deep down in the
                # call chain. So we monkey patch the SIGINT to SIGTERM for the
                # duration of the call.
                signal.SIGINT = signal.SIGTERM
            postgresql.stop()
            _INITIALIZED = False
        finally:
            if _IS_WINDOWS:
                signal.SIGINT = prev_sig_int


def db_test_env_init(strict: bool = False) -> str:
    """Initializes test database."""
    global _INITIALIZED
    with _LOCK:
        if _INITIALIZED:
            if strict:
                raise RuntimeError("Test database already initialized")
            return os.environ["DB_URL"] or ""
        postgresql = testing.postgresql.Postgresql()
        url = postgresql.url()
        os.environ["DB_URL"] = url
        _INITIALIZED = True
        atexit.register(_db_test_env_teardown, postgresql)
        return url

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

No branches or pull requests

8 participants