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

Handling of SIGTERM in kiwix-serve #488

Merged
merged 1 commit into from Oct 18, 2021
Merged

Conversation

veloman-yunkan
Copy link
Collaborator

Fixes #482

@kelson42
Copy link
Contributor

kelson42 commented Oct 9, 2021

@rgaudin Would you be able to check please that the handling in Docker works now please?

@rgaudin
Copy link
Member

rgaudin commented Oct 11, 2021

@rgaudin Would you be able to check please that the handling in Docker works now please?

I'd like to but I am having difficulties buidling a static kiwix-serve. @veloman-yunkan can you share a static linux build that I could try?

@veloman-yunkan
Copy link
Collaborator Author

@rgaudin Would you be able to check please that the handling in Docker works now please?

I'd like to but I am having difficulties buidling a static kiwix-serve. @veloman-yunkan can you share a static linux build that I could try?

@rgaudin Here you are

@rgaudin
Copy link
Member

rgaudin commented Oct 12, 2021

@veloman-yunkan, thank you. kiwix-serve now properly shuts down on docker stop and docker restart works as expected.

Unfortunately, it doesn't react anymore to ^C so when using it with docker run -it, it can't be stopped in the same terminal.

FROM alpine

RUN mkdir -p /data && wget -O /data/archlinux_en_all_maxi_2021-05.zim https://download.kiwix.org/zim/other/archlinux_en_all_maxi_2021-05.zim

VOLUME /data

RUN wget https://github.com/kiwix/kiwix-tools/files/7324533/kiwix-serve.gz && \
    gunzip kiwix-serve.gz && \
    mv kiwix-serve /usr/local/bin/ && \
    chmod +x /usr/local/bin/kiwix-* && \
    rm -rf /kiwix-serve.gz

CMD ["/usr/local/bin/kiwix-serve", "/data/archlinux_en_all_maxi_2021-05.zim"]
docker build . -t kst && docker run -p 9999:80 -it kst

@mgautierfr
Copy link
Member

LGTM.
But we must fix the last comment raised by @rgaudin (I don't know why it doesn't react anymore to SIGINT)

@veloman-yunkan
Copy link
Collaborator Author

Unfortunately, it doesn't react anymore to ^C so when using it with docker run -it, it can't be stopped in the same terminal.

@rgaudin The fix is easy - SIGINT must be handled in exactly the same way as SIGTERM.

For some reason I cannot upload the new build to github. Please let me know if you want to test it too.

@veloman-yunkan
Copy link
Collaborator Author

LGTM. But we must fix the last comment raised by @rgaudin (I don't know why it doesn't react anymore to SIGINT)

@mgautierfr Since the full change is small, I amended my fix and force pushed it without using a temporary fix-up commit.

@kelson42
Copy link
Contributor

kelson42 commented Oct 13, 2021

What about all the other standard singals which were working. I think in particular to SiGSTP which is really useful?

@veloman-yunkan
Copy link
Collaborator Author

This fix addresses handling of signals in kiwix-serve when it is executed with PID=1 (see https://petermalmgren.com/signal-handling-docker/). Otherwise, all other signals work as before. I don't think that suspending a process with PID=1 on SIGSTP makes any sense.

@mgautierfr
Copy link
Member

For what I understand, the root cause of all this is that we are running the process with PID=1. So no default signal handler are used by the kernel. (@veloman-yunkan do you confirm ?)

Instead of re implement them wouldn't be better to use tools like https://github.com/Yelp/dumb-init or https://github.com/krallin/tini ?

@rgaudin
Copy link
Member

rgaudin commented Oct 13, 2021

Agrees with @mgautierfr. I've tested dumb-init quickly and it seems to work fine in all of my scenarios. Preparing a PR

rgaudin added a commit that referenced this pull request Oct 13, 2021
Following-up on discussion in #488, now using https://github.com/Yelp/dumb-init
as entrypoint so our kiwix-* tools properly receives signals
rgaudin added a commit that referenced this pull request Oct 13, 2021
Following-up on discussion in #488, now using https://github.com/Yelp/dumb-init
as entrypoint so our kiwix-* tools properly receives signals
@rgaudin
Copy link
Member

rgaudin commented Oct 13, 2021

See #489, for an alternative using dumb-init

rgaudin added a commit that referenced this pull request Oct 13, 2021
Following-up on discussion in #488, now using https://github.com/Yelp/dumb-init
as entrypoint so our kiwix-* tools properly receives signals
@veloman-yunkan
Copy link
Collaborator Author

For what I understand, the root cause of all this is that we are running the process with PID=1. So no default signal handler are used by the kernel. (@veloman-yunkan do you confirm ?)

I confirm that.

Instead of re implement them wouldn't be better to use tools like https://github.com/Yelp/dumb-init or https://github.com/krallin/tini ?

For kiwix docker images that solution will work too. However it won't render this fix meaningless, since the latter provides a clean way of shutting down the server.

kelson42 pushed a commit that referenced this pull request Oct 14, 2021
Following-up on discussion in #488, now using https://github.com/Yelp/dumb-init
as entrypoint so our kiwix-* tools properly receives signals
@@ -79,7 +79,7 @@ void usage()
<< std::endl;
}

bool waiting = true;
volatile sig_atomic_t waiting = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch !

@mgautierfr
Copy link
Member

For kiwix docker images that solution will work too. However it won't render this fix meaningless, since the latter provides a clean way of shutting down the server.

I agree.

And I wonder if we should not reset the signal handling to the default one after we handle it (or correctly handle a second signal). If something goes wrong during the server.stop() user would be able to kill the process with another Ctrl-C.
This is something I see few times on process taking times to clean up. A first ``Ctrl-C` is handled by the process with a message kind of
"Stopping the server... A new Ctrl-C will quit the process right now."

This is less important for SIGTERM as it is used by system before shutdown and a SIGKILL will be used just after if process doesn't quit.
We may also want to handle the signal raised before the server is started.
The easier is probably to init the wainting boolean to false, set it to true just before starting the server. And if wainting is false during the signal handling exit the process directly.

@veloman-yunkan
Copy link
Collaborator Author

veloman-yunkan commented Oct 17, 2021

For kiwix docker images that solution will work too. However it won't render this fix meaningless, since the latter provides a clean way of shutting down the server.

I agree.

And I wonder if we should not reset the signal handling to the default one after we handle it (or correctly handle a second signal). If something goes wrong during the server.stop() user would be able to kill the process with another Ctrl-C. This is something I see few times on process taking times to clean up. A first ``Ctrl-C` is handled by the process with a message kind of "Stopping the server... A new Ctrl-C will quit the process right now."

This is less important for SIGTERM as it is used by system before shutdown and a SIGKILL will be used just after if process doesn't quit. We may also want to handle the signal raised before the server is started. The easier is probably to init the wainting boolean to false, set it to true just before starting the server. And if wainting is false during the signal handling exit the process directly.

@mgautierfr In kiwix-serve SIGINT and SIGTERM should be handled identically. SIGINT has a different semantics for interactive applications, where it is intended to interrupt the current action invoked by the user (for example, in interactive python interpreter Ctrl-C interrupts the evaluation of the current expression entered in the REPL, but doesn't terminate the interpreter itself). In our case, the current action is the execution of the server in its entirety, that's why the effect of Ctrl-C should be indistinguishable from SIGTERM.

I implemented the handling of a second SIGINT or SIGTERM signal (or the first signal before the server loop is entered) without resorting to the default method. Then this fix keeps working for PID=1 processes too without relying on dumb-init or a similar workaround.

@mgautierfr
Copy link
Member

Yes, we agree.
What I was saying is that we don't need to be prepare for a second SIGTERM as it should be followed by a SIGKILL (if something goes wrong when we quit our process). On the contrary, if something goes wrong when we quit after a first SIGINT, the user will send a second one.
But both (first) SIGTERM and SIGINT must be handled the same. And it is not a problem if we are handling the second SIGTERM the same way that SIGINT.

@mgautierfr mgautierfr merged commit 7659efa into master Oct 18, 2021
@mgautierfr mgautierfr deleted the kiwix-serve_sigterm_handling branch October 18, 2021 08:42
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.

kiwix-serve should handle signals within docker
4 participants