GithubHelp home page GithubHelp logo

Comments (25)

barakmich avatar barakmich commented on July 17, 2024

I believe this is the same issue that #100 got around for the integration test, but should be stomped out once and for all

from cayley.

kortschak avatar kortschak commented on July 17, 2024

@scampi Would you please post which version of cayley you were running when this happened and what configuration you were using?

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

+1 reproduced the same bug on cayley from master

from cayley.

kortschak avatar kortschak commented on July 17, 2024

The issue here is that kill chan persists over the course of the session. This means that there is a race that allows a brief window when s.kill has been replaced and an old func·011 has not yet fired the close signal. The kill chan can then be closed and a new func·011 is started with a now closed chan. We could engineer something around this, but I think it's probably best to just use tomb since the engineering there has already been done: http://godoc.org/gopkg.in/tomb.v2 (3-clause BSD-like).

from cayley.

barakmich avatar barakmich commented on July 17, 2024

Tomb SGTM. We entomb the wait-and-kill goroutine and kill the killer on success? (As violent as that sounds)

from cayley.

kortschak avatar kortschak commented on July 17, 2024

I need to read what Gustavo suggests, but we should be able to have a type that encapsulates the otto session. It should be less invasive than having to kill everyone involved.

from cayley.

kortschak avatar kortschak commented on July 17, 2024

I've just had a look into this and it's more complicated to use tomb than I though for this case. However, if my diagnosis is correct above, the following code should fix it. @scampi and @0xAX would you try to reproduce with gremlin.(*Session).runUnsafe replaced with the following:

func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
    defer func() {
        if r := recover(); r != nil {
            if r == ErrKillTimeout {
                s.err = ErrKillTimeout
                return
            }
            panic(r)
        }
    }()

    // Use buffered chan to prevent blocking.
    s.env.Interrupt = make(chan func(), 1)

    ready := make(chan struct{})
    s.kill = make(chan struct{})
    if s.timeout >= 0 {
        go func() {
            time.Sleep(s.timeout)
            <-ready
            close(s.kill)
            s.envLock.Lock()
            defer s.envLock.Unlock()
            if s.env != nil {
                s.env.Interrupt <- func() {
                    panic(ErrKillTimeout)
                }
                s.env = s.emptyEnv
            }
        }()
    }

    s.envLock.Lock()
    env := s.env
    s.envLock.Unlock()
    close(ready)
    return env.Run(input)
}

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

Hello @kortschak,

applied your patch, the same crash for me

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

btw @kortschak i'm very interesting in cayley and contributing to it, now i'm reading source code of it and try to fix current bug and have a one question. How to print something custom in repl for debugging? I see that everywhere is fmt.Printf for output but i tried to put fmt.Printf in runUnsafe and go build cayley but nothing printed.

so your patch can be fix for this bug, but seems that changes doesn't apply after go build

from cayley.

kortschak avatar kortschak commented on July 17, 2024

FIrst, let's get the obvious out of the way. I'm assuming you built and installed the changed code.

Can you post a gist with the output of `git diff' from within the cayley repo when you have your changes in place?

from cayley.

kortschak avatar kortschak commented on July 17, 2024

Ian this is why I shouldn't do anything when I'm sick. I see you are using go build. For the sake of simplicity in explanation here, don't do that. go build does a build, and unless the object is an executable, the result is discarded, so unless you are doing go build in the cayley directory, the effect is just a check for compilability. Use go install, from within the cayley directory - because of the speed of compilation, clobbering your installed cayley should not be an issue.

from cayley.

barakmich avatar barakmich commented on July 17, 2024

I tried it too -- no dice. The simple way to reproduce is to run the sample memstore with -timeout 5s -- run g.V().All() (give it something to do) and up-enter whenever you get a prompt.

The problem being, much like s.env, used to be, there's a couple goroutines then floating about pointing at s.kill

There's https://github.com/barakmich/cayley/commits/replcrash with my go at it that seems to help.

from cayley.

kortschak avatar kortschak commented on July 17, 2024

I'm afraid that's racey. This is the kind of thing I was trying to avoid with my fix, but I'm not firing on all cylinders right now.

The issue I think comes down to a conflict of contractual expectations. A session is only contractually expected to run once, but in the REPL we give it a number of snippets of code to run. What needs to happen is that each snippet gets it's own killer. So probably it needs to be organised as a Session with workers that each only can be run once.

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

Ian this is why I shouldn't do anything when I'm sick. I see you are using go build. For the sake of simplicity in explanation here, don't do that. go build does a build, and unless the object is an executable, the result is discarded, so unless you are doing go build in the cayley directory, the effect is just a check for compilability. Use go install, from within the cayley directory - because of the speed of compilation, clobbering your installed cayley should not be an issue.

Yes, i tried go build in cayley directory. Now look:

For example i just added fmt.Println(s.timeout) before https://github.com/google/cayley/blob/master/query/gremlin/session.go#L128, after it i executed go install and it nothing print after starting repl

from cayley.

kortschak avatar kortschak commented on July 17, 2024

Works for me using both methods.

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

ah @kortschak sorry for this, found a problem.

from cayley.

0xAX avatar 0xAX commented on July 17, 2024

@kortschak, @barakmich tested cayley with c1ff6ce and can't reproduce this bug

from cayley.

barakmich avatar barakmich commented on July 17, 2024

And I'm having trouble recreating the race. The first race I got was actually in peterh/liner.

Meanwhile, I'm going to merge my patch, to halt the bleeding, because it's really bad right now.

I'm not saying it's fixed by any means; I'm leaving this bug open and changing its scope to be "Fix Sessions to properly manage worker routines", which is the correct fix as @kortschak mentions.

from cayley.

kortschak avatar kortschak commented on July 17, 2024

Yeah, no worries. I have a plan for a fix, but I have not had the time to work it up yet.

Do you have the race warning for liner?

from cayley.

barakmich avatar barakmich commented on July 17, 2024

Happened to be in my scrollback:

cayley> ==================
WARNING: DATA RACE
Read by goroutine 9:
  github.com/peterh/liner.(*State).WriteHistory()
      /home/barak/src/cayley/src/github.com/peterh/liner/common.go:61 +0x6c
  github.com/google/cayley/db.persist()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:199 +0x25a
  github.com/google/cayley/db.func·002()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:173 +0x195

Previous write by main goroutine:
  [failed to restore the stack]

Goroutine 9 (running) created at:
  github.com/google/cayley/db.terminal()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:182 +0xe2
  github.com/google/cayley/db.Repl()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:86 +0x188
  main.main()
      /fs/home/barak/src/cayley/src/github.com/google/cayley/cayley.go:164 +0x13b8
==================
==================
WARNING: DATA RACE
Read by goroutine 9:
  github.com/peterh/liner.(*State).WriteHistory()
      /home/barak/src/cayley/src/github.com/peterh/liner/common.go:61 +0xce
  github.com/google/cayley/db.persist()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:199 +0x25a
  github.com/google/cayley/db.func·002()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:173 +0x195

Previous write by main goroutine:
  [failed to restore the stack]

Goroutine 9 (running) created at:
  github.com/google/cayley/db.terminal()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:182 +0xe2
  github.com/google/cayley/db.Repl()
      /home/barak/src/cayley/src/github.com/google/cayley/db/repl.go:86 +0x188
  main.main()
      /fs/home/barak/src/cayley/src/github.com/google/cayley/cayley.go:164 +0x13b8
==================

from cayley.

kortschak avatar kortschak commented on July 17, 2024

OK, so that must have happened in response to a ^C.

I can see why it's there, and I am causing it, but I can't see a way to fix it.

I will file an issue against liner to get @peterh's view.

from cayley.

barakmich avatar barakmich commented on July 17, 2024

Yeah, it did, actually.

from cayley.

peterh avatar peterh commented on July 17, 2024

Hmm. At a guess, you're trying to save history from a goroutine that is responding to Ctrl-C while another goroutine is still inside Prompt(). That's not supported. Or, at least, it wasn't. Could you please give peterh/liner@16acdab a spin, and let me know if that fixes things?

from cayley.

kortschak avatar kortschak commented on July 17, 2024

Thanks Peter, that was my feeling, and your fix looks exactly like what I was thinking. I will try it when I get to work.

from cayley.

kortschak avatar kortschak commented on July 17, 2024

@peterh, that fix works as expected, thanks.

from cayley.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.