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

Unsafe concurrent operations on #<HASH-TABLE :TEST EQ :COUNT 29 {1002361DF3}> detected. #3

Closed
svetlyak40wt opened this issue Oct 26, 2020 · 7 comments

Comments

@svetlyak40wt
Copy link

I've encountered this error when tried to run this code on SBCL 2.0.8:

POFTHEDAY> (cl-async-await:defun-async http-get (url &rest args)
             (apply #'dexador:get url args))
HTTP-GET
POFTHEDAY> (defun do-the-test ()
             (let ((promises
                     (loop repeat 100
                           collect (http-get "https://httpbin.org/delay/5"))))
               ;; Now we have to fetch results from our promises.
               (loop for promise in promises
                     for response = (cl-async-await:await
                                     promise)
                     summing (length response))))
DO-THE-TEST
POFTHEDAY> (do-the-test)

Full trace:

Unsafe concurrent operations on #<HASH-TABLE :TEST EQ :COUNT 29 {1002361DF3}> detected.
   [Condition of type SIMPLE-ERROR]

Restarts:
 0: [ABORT] Terminate the promise's thread.
 1: [ABORT] abort thread (#<THREAD "PROMISE-THREAD" RUNNING {10057C9CA3}>)
 2: [RETRY] Retry SLY mREPL evaluation request.
 3: [*ABORT] Return to SLY's top level.
 4: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {100383CD53}>)

Backtrace:
 0: ((LAMBDA ()))
      Locals:
        CL-ASYNC-AWAIT::RESTART-INVOKED = NIL
 1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (LET ((CL-ASYNC-AWAIT::RESTART-INVOKED NIL)) (UNWIND-PROTECT (RESTART-CASE # # #) (UNLESS CL-ASYNC-AWAIT::RESTART-INVOKED # #))) #<NULL-LEXENV>)
      Locals:
        SB-KERNEL:LEXENV = #<NULL-LEXENV>
        SB-IMPL::ORIGINAL-EXP = (LET ((CL-ASYNC-AWAIT::RESTART-INVOKED NIL)) ..)
 2: (EVAL (LET ((CL-ASYNC-AWAIT::RESTART-INVOKED NIL)) (UNWIND-PROTECT (RESTART-CASE # # #) (UNLESS CL-ASYNC-AWAIT::RESTART-INVOKED # #))))
      Locals:
        SB-IMPL::ORIGINAL-EXP = (LET ((CL-ASYNC-AWAIT::RESTART-INVOKED NIL)) ..)
 3: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-THREAD::CALL-WITH-MUTEX))
      Locals:
        GOT-IT = T
        MUTEX = #<SB-THREAD:MUTEX "PROMISE-MUTEX" owner: #<SB-THREAD:THREAD "sly-channel-1-mrepl-remote-1" RUNNING {100383CD53}>>
 4: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN CL-ASYNC-AWAIT:AWAIT) {20DACBB}> #<SB-THREAD:MUTEX "PROMISE-MUTEX" owner: #<SB-THREAD:THREAD "sly-channel-1-mrepl-remote-1" ..
      Locals:
        GOT-IT = T
        MUTEX = #<SB-THREAD:MUTEX "PROMISE-MUTEX" owner: #<SB-THREAD:THREAD "sly-channel-1-mrepl-remote-1" RUNNING {100383CD53}>>
        SB-C::THING = #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN CL-ASYNC-AWAIT:AWAIT) {20DACBB}>
        TIMEOUT = NIL
        WAITP = T
 5: ((:METHOD CL-ASYNC-AWAIT:AWAIT (CL-ASYNC-AWAIT:PROMISE)) #<CL-ASYNC-AWAIT:PROMISE (ERROR Unsafe concurrent operations on #<HASH-TABLE :TEST EQ :COUNT 29 {1002361DF3}> detected. RESTARTS ((NAME ABORT R..
 6: (DO-THE-TEST)
@svetlyak40wt
Copy link
Author

This problem is not stable reproducible. Sometimes it requires to run (do-the-test) more than once.

But after it happened, consequent calls fail with the same problem.

@svetlyak40wt
Copy link
Author

Probably, this issue really is issue of the dexador: fukamachi/dexador#88 because adding :use-connection-pool nil :keep-alive nil seems fixes it.

But even if it is a dexador's problem, then it is completely difficult to debug because of the wrong backtrace :(

@j3pic
Copy link
Owner

j3pic commented Oct 27, 2020

I'm considering reverting the rewrite I did a while back (see #4). If I do it, the result will be a library that does everything in one thread, much like what this style of promise originally did in JavaScript. This problem would go away (though others would be introduced and there'd be a loss of functionality).

I recommend that you use lparallel instead, since it does what CL-ASYNC-AWAIT currently does, only better. It doesn't have the stack trace bug. Your example program would look like this:

(defun do-the-test ()
  (let ((promises (loop repeat 100
			    collect (lparallel:future (dexador:get "https://httpbin.org/delay/5")))))
    (loop for promise in promises
	      sum (length (lparallel:force promise)))))

@svetlyak40wt
Copy link
Author

Cool! I didn't know about such functionality in lparallel!

@vindarel
Copy link

vindarel commented Nov 3, 2020

what CL-ASYNC-AWAIT currently does

Does that mean you have plans for cl-async-await?

thanks

@j3pic
Copy link
Owner

j3pic commented Nov 6, 2020

As a matter of fact, I do. See #1 for details.

@ajberkley
Copy link

I know this is closed, but this was a dexador problem and has since been fixed.

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

4 participants