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

"eval" within "multi" crashes DF #457

Closed
boazsade opened this issue Nov 2, 2022 · 7 comments
Closed

"eval" within "multi" crashes DF #457

boazsade opened this issue Nov 2, 2022 · 7 comments
Assignees
Labels
bug Something isn't working

Comments

@boazsade
Copy link
Contributor

boazsade commented Nov 2, 2022

Describe the bug
When running pipeline test from ioredis, we are getting stuck. This is a result of a pipeline test that execute the commands: set, eval and get. The end result is that we are not returning to the client and DF cannot be shutdown as it is stuck on a command that never completed.

To Reproduce
Steps to reproduce the behavior:
1.multi
2. set foo asdf
3. EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
4. get foo
5. exec
This command would not "return", the connection will stay opened even when the connection is closed on the Redis, client side.
You would not be able to shutdown DF.

Expected behavior
This should return a result for the client:

1) OK
2) 1) "key1"
   2) "key2"
   3) "first"
   4) "second"
3) "asdf"

And we should be able to shutdown DF after that.

Environment (please complete the following information):

Reproducible Code Snippet

it("should be supported in transaction blocks", (done) => {
      redis
        .pipeline()
        .multi()
        .set("foo", "asdf")
        .echo("bar", "baz", "123", "abc")
        .get("foo")
        .exec()
        .exec(function (err, results) {
          expect(err).to.eql(null);
          expect(results[4][1][1]).to.eql(["bar", "baz", "123", "abc"]);
          expect(results[4][1][2]).to.eql("asdf");
          done();
        });
    });
  });

Additional context
This code would work:

 it("should support callbacks", (done) => {
      let pending = 1;
      redis
        .pipeline()
        .echo("foo", "bar", "123", "abc", function (err, result) {
          pending -= 1;
          expect(err).to.eql(null);
          expect(result).to.eql(["foo", "bar", "123", "abc"]);
        })
        .exec(function (err, results) {
          expect(err).to.eql(null);
          expect(results).to.eql([[null, ["foo", "bar", "123", "abc"]]]);
          expect(pending).to.eql(0);
          done();
        });
    });
@boazsade boazsade added the bug Something isn't working label Nov 2, 2022
@boazsade boazsade self-assigned this Nov 3, 2022
@boazsade
Copy link
Contributor Author

boazsade commented Nov 6, 2022

Once this is resolved, please update the list of supported tests in ioredis

@boazsade
Copy link
Contributor Author

boazsade commented Nov 7, 2022

This is triggered by "transaction.cc:420] Check failed: 0u == txid_ (0 vs. 1)"
To reproduce this the only requirement is to do:

  1. MULTI
  2. EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
  3. EXEC
    This would trigger the crash.
    When in release mode, and there are more commands in the transaction it would not crash but hung

@romange
Copy link
Collaborator

romange commented Nov 7, 2022 via email

@boazsade
Copy link
Contributor Author

boazsade commented Nov 7, 2022

yes

@boazsade
Copy link
Contributor Author

boazsade commented Nov 7, 2022

The issue is triggered by running transaction within transaction. This happens because we have:

  1. EXEC is starting a transaction (in the context of multi)
  2. Then from within this transaction we scheduling transaction operation from the script context, This calls the function "ScheduleInternal" which verifies that its the a clean transaction state (transaction id == 0). But this is not true any more, since we already pass through this function at step 1.

The fix for this would require supporting this type of flow - starting a context of transaction and then running a script that requires its own context.

For now I will try to issue a workaround that would fail this operation (would not allow for running script inside "multi"). so the result would not be either a crash or that the context is hung and the the application cannot even shutdown as it is now.
I will also add a test to verify for now that we are getting an error and not other issue, and once this is fixed, we would see that this test would fail

boazsade added a commit to boazsade/dragonfly that referenced this issue Nov 8, 2022
…inside multi dragonflydb#457

Signed-off-by: Boaz Sade <boaz@dragonflydb.io>
boazsade added a commit to boazsade/dragonfly that referenced this issue Nov 9, 2022
Signed-off-by: Boaz Sade <boaz@dragonflydb.io>
boazsade added a commit to boazsade/dragonfly that referenced this issue Nov 9, 2022
Signed-off-by: Boaz Sade <boaz@dragonflydb.io>
@romange romange changed the title Running pipeline command with "set" "eval" "get" would hung connection and will not allow DF to shutdown "eval" within "mult" crashes DF Nov 9, 2022
@romange romange changed the title "eval" within "mult" crashes DF "eval" within "multi" crashes DF Nov 9, 2022
@romange
Copy link
Collaborator

romange commented Nov 9, 2022

Fixed

@romange romange closed this as completed Nov 9, 2022
@boazsade
Copy link
Contributor Author

boazsade commented Nov 9, 2022

Just note that this is a temporary fix - we have issue #467 as a flow-up for it. There is also a branch issue-467, to work on it

romange pushed a commit that referenced this issue Nov 9, 2022
fix(server): block running lua script inside pipeline #457

Signed-off-by: Boaz Sade <boaz@dragonflydb.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants