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

Cancel future returned from run_in_executor caused SIGTERM signal to main process #135

Closed
yli02 opened this issue Jun 6, 2024 · 1 comment

Comments

@yli02
Copy link

yli02 commented Jun 6, 2024

Hi, thanks for your effort in developing and maintaining this very good library. It is very helpful for me to use it with asyncio.

I found one strange behavior but not sure whether it could be considered as a bug. If you run the following code in a python file, the main process where the event loop run get SIGTERM signal after the cancellation of a running future. This is fine if the main process just ignore it, however, for my real code running in K8S, the SIGTERM signal is handled in main process for graceful shutdown in case of pod scaling down. Therefore, the cancellation of a future causing graceful shutdown is not really what I want.

Could you have a look at the code and see whether this is a bug? If it is not, do you have any suggestion about how could I avoid receiving SIGTERM in main process in case of cancelling running future. Thanks a lot.

import asyncio
import time
from functools import partial
import signal

from pebble import ProcessPool


def cpu_bound_task():
    print(f"CPU task started")
    time.sleep(30)
    print(f"CPU task completed")


async def cancel_future(future):
    print('cancel future')
    # to give the cpu task a chance to start
    await asyncio.sleep(5)
    cancel_result = future.cancel(msg='cancel future due to OOM')
    print(f"done cancel: {cancel_result}")


async def main():
    pool = ProcessPool(max_workers=2)
    loop = asyncio.get_running_loop()

    loop.add_signal_handler(
        signal.SIGTERM,
        lambda: print("SIGTERM received")
    )

    func_in_executor = partial(cpu_bound_task)
    result_future = loop.run_in_executor(pool, func_in_executor, 0)

    try:
        results = await asyncio.gather(
            cancel_future(result_future),
            result_future,
            # return_exceptions=True
        )

        for res in results:
            print(res, type(res))

    except asyncio.CancelledError:
        print('gather is cancelled')

    await asyncio.sleep(30)

    print("done sleep in main")


if __name__ == "__main__":
    asyncio.run(main())
@yli02
Copy link
Author

yli02 commented Jun 6, 2024

Hi, I found that this seems to be related to issue #66, I will close this one.

@yli02 yli02 closed this as completed Jun 6, 2024
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

1 participant