Skip to content

Add support for gevent - #6372

Open
skiedude wants to merge 20 commits into
StackStorm:masterfrom
skiedude:eventlet_death
Open

Add support for gevent#6372
skiedude wants to merge 20 commits into
StackStorm:masterfrom
skiedude:eventlet_death

Conversation

@skiedude

@skiedude skiedude commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

concurrency.py was started previously and this PR finishes its integration. Any part of the code that needs to manipulate/create/use/destroy an eventlet/gevent object has to do so using concurrency helpers.

  1. A new [system] level conf key of concurrency_library is now available. If its unset, it will default to gevent but can be set to eventlet if desired.
  2. add helper methods for every type of concurrency operation and update all files throughout all services/tests to use the concurrency library (if we ever have to migrate this again, this should hopefully make it easier).

I performed local testing using a local docker setup that was running all services on the updated code. A new pack was created to specifically test concurrency type features as well: https://github.com/skiedude/concurrency-test-pack/tree/main (should consider redoing these actions a bit to make them runnable through future PRs?)

Claude aided in the development and testing of this PR.

nzlosh and others added 7 commits February 19, 2026 08:53
* Bump pip and setuptools and switch from setup.py to pip install

* Add gevent to requirements, bumps for compatibility and regenerate requirement files.

* Display which components fail unit tests.

* Add checks for eventlet code in monkey patch
@pull-request-size pull-request-size Bot added the size/XXL PR that changes 1000+ lines. You should absolutely split your PR into several. label Mar 26, 2026
@guzzijones

Copy link
Copy Markdown
Contributor

looks like you have some failing unit tests

skiedude and others added 3 commits July 17, 2026 10:21
- Took upstream's CI image bumps (py3.10, mongo 8.2, rabbitmq 4.2) in .circleci/config.yml
- Merged Makefile: kept setuptools_scm/python -m build (needed for gevent's setuptools pin), took upstream's $(PYBIN) consistency
- fixed-requirements.txt: kept gevent/eventlet/greenlet/gunicorn pins, dropped unused flex, picked up importlib_resources/importlib_metadata
- Regenerated all per-component requirements.txt via make requirements
- Regenerated lockfiles/st2.lock via pants generate-lockfiles --resolve=st2
- st2client httpclient.py: resolved shlex.quote alias naming
- test_service_setup_log_level_filtering.py: kept concurrency.sleep() abstraction, took upstream's SIGTERM/8s timeout flakiness fix
Comment thread st2common/st2common/util/concurrency.py Outdated
@guzzijones

Copy link
Copy Markdown
Contributor

can we just switch to gevent. why have a variable?

skiedude and others added 9 commits August 12, 2026 14:52
- Read concurrency_library from st2.conf [system] instead of an env var,
  defaulting to gevent.
- Pick the gunicorn worker class (-k eventlet/-k gevent) dynamically based
  on the configured concurrency library instead of hardcoding eventlet.
- Fix real gevent bugs: wrap_ssl() using the removed ssl.wrap_socket(),
  green_pool_wait_all() not actually blocking, wait() not returning the
  greenlet's result, and several call sites bypassing the concurrency
  wrapper with direct .wait()/.free() calls on greenlets/pools.
- Fix a gevent-only hang in the python runner: process.stdin was written
  to but never closed/flushed for large (>64KB) parameters, leaving the
  child process blocked forever waiting for input that never arrived.
- Remove remaining direct eventlet imports outside the concurrency
  compatibility layer (tools, examples, test mocks); keep back-compat
  aliases (EventletTestCase, setup_eventlet_profiler,
  blocking_eventlet_spawn) for external callers.
Both conf/st2.tests.conf (used by subprocess-spawning integration tests)
and st2tests/conf/st2.conf now explicitly set concurrency_library = gevent
instead of silently relying on the code-level fallback default.
…ify library loading

conftest.py now monkey patches before any test module is imported, whether
pytest runs a whole directory or a single file in isolation (as Pants does
in CI). Without this, tooz's Heart binds threading.Thread/Event as default
args at import time; if tooz gets imported before patching, it permanently
uses the unpatched primitives, causing gevent.exceptions.LoopExit or hangs
in test_synchronization.py, test_worker.py, and test_service_registry.py.

concurrency.py now only imports the concurrency library that's actually
active, replaces the CONCURRENCY_LIBRARY/eventlet/gevent globals with a
single state object, and consolidates every eventlet/gevent submodule
import into one place instead of scattering local imports across each
helper function.
Sweep of every file importing concurrency.py for objects created via its
factory functions (spawn/Semaphore/Queue/green pools) that still called
library-specific methods directly instead of going through the wrapper.
Adds link(), pool_spawn(), and resize_green_pool() wrappers and updates
their call sites in actionrunner.py, workflow_engine.py, scheduler/handler.py,
greenpooldispatch.py, wsgi.py, parallel_ssh.py, consumers.py,
st2-inject-trigger-instances.py, and the corresponding test files.

Also defers actionrunner.py/workflow_engine.py's SIGTERM handlers to
concurrency.spawn(...) instead of calling .kill() synchronously from the
raw signal callback, since gevent raises BlockingSwitchOutError for
blocking greenlet operations invoked directly from a signal handler
(eventlet has no such restriction).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XXL PR that changes 1000+ lines. You should absolutely split your PR into several.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants