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

hiredis blocking uninterruptible #1158

Open
RP991 opened this issue Jan 24, 2023 · 2 comments
Open

hiredis blocking uninterruptible #1158

RP991 opened this issue Jan 24, 2023 · 2 comments
Assignees

Comments

@RP991
Copy link

RP991 commented Jan 24, 2023

I recently upgraded our hiredis client library from 0.10.1 to 1.1.0.
Following the upgrade, our processes that use the BRPOPLPUSH verb ceased
responding to SIGINT or SIGTERM, i.e. became uninterruptible while blocked
waiting for a new element on the list. The processes in question have
been running for years happily with the old driver.

I tracked this down to a change in the handling of the error return from recv()
(net.c redisNetRead() in the case of 1.1.0), versus similar handling for read()
in the old version (hiredis.c redisBufferRead() in 0.10.1).

The old version used to respond to EINTR by setting REDIS_ERR_IO with
__redisSetError(c,REDIS_ERR_IO,NULL) and return REDIS_ERR (-1).

The new version "ignores" EINTR by returning 0 from redisNetRead(), without
setting REDIS_ERR_IO. This in turn prevents redisGetReply() from ever
breaking out of the while(aux == NULL) loop.

I changed redisNetRead() to treat EINTR as it used to, by calling
__redisSetError(c, REDIS_ERR_IO, strerror(errno)); and returing -1, which
solves the problem for me.

Have I misunderstood something, or is this a bug? If so, is my fix the
correct way to rectify it?

@michael-grunder michael-grunder self-assigned this Jan 24, 2023
@michael-grunder
Copy link
Collaborator

Thanks for the report.

It looks like this change was made very early in the project (see: #99). It appears that the consensus was that hiredis should retry when the system call was interrupted as EINTR doesn't imply an error state.

Since this has been the functionality for so long we can't really change it. One possible solution would be to create a SIGINT/SIGTERM handler where you could set the redisReader error state, although that's kind of messy.

Another possible solution would be if we added an option that would configure redisContext to treat EINTR as an error.

It's also possible to just override the redisContext->funcs->read with your own function that handles EINTR differently. People do this a fair bit, but right now there's not a nice API to override the functions, and they are defined const.

@RP991
Copy link
Author

RP991 commented Jan 24, 2023 via email

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

2 participants