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

Deadlock calling GroundedSchema/Predicate written in Python in OpenPsi #3510

Open
stellarspot opened this issue May 28, 2019 · 1 comment
Open

Comments

@stellarspot
Copy link
Contributor

Below is a simple usage of OpenPsi which calls methods from Python:

import time
from opencog.type_constructors import *
from opencog.utilities import initialize_opencog
from opencog.bindlink import execute_atom, evaluate_atom

# Initialize AtomSpace
atomspace = AtomSpace()
initialize_opencog(atomspace)


# Called by OpenPsi Action
def eat_apple(apple):
    print("[openpsi] eat apple:", apple.name)
    return ConceptNode("finished")


# Call Scheme
from opencog.scheme_wrapper import scheme_eval

scheme_eval(atomspace,
            '''
(use-modules
 (opencog)
 (opencog openpsi))

; OpenPsi sample
; Eat apples

(define apple (Concept "apple"))

; OpenPsi Goal: eat apples
(define goal
 (Concept "goal-eat-apples"))

(define context
 (list
  (Inheritance (Variable "$APPLE") apple)))

; OpenPsi Action: eat apple
(define action
 (ExecutionOutput
  (GroundedSchema "py: eat_apple")
  (List
   (Variable "$APPLE")
  )))

(define (eat-apple apple)
 (display "[openpsi] eat apple action\n")
 (display apple)
 (ConceptNode "finished"))

(define component (psi-component "component"))

(define rule
 (psi-rule
  context
  action
  goal
  (stv 1 1)
  component))

(psi-run component)
            ''')

InheritanceLink(ConceptNode("apple-1"), ConceptNode("apple"))
InheritanceLink(ConceptNode("apple-2"), ConceptNode("apple"))


def check_apples():
    print("[python] check apples")
    return TruthValue(1.0, 1.0)


while (True):
    time.sleep(0.2)
    query = EvaluationLink(
        GroundedPredicateNode("py: check_apples"),
        ListLink())
    res = evaluate_atom(atomspace, query)
    print("check apples:", res)

scheme_eval(atomspace, "(psi-halt component)")

Running this code leads to deadlock.

@stellarspot
Copy link
Contributor Author

There are two threads. The first is where Python runs its code and the second which is run by OpenPsi.
OpenPsi thread calls Python method eat_apple(apple) using GroundedSchema.
Python thread calls Python method check_apples() using GroundedPredicate.

The deadlock happens in the following scenario:

  • Python thread acquires GIL
  • OpenPsi starts calling a Python GroundedSchema method
  • OpenPsi thread locks mutex in the method: PythonEval::call_user_function(...)
  • OpenPsi waits for the GIL in the PythonEval::call_user_function(...)
  • Python starts calling a Python GroundedPredicate method
  • Python waits for the locked mutex in the PythonEval::apply_tv(...)

It seems from the Python perspective PythonEval methods first needs to acquire GIL and the mutex after it. In this case the deadlock does not happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants