leonoel/missionary

`ap` bug

leonoel opened this issue · 2 comments

(def input (m/observe (fn [!] (def i! !) #(do))))

(def ps
  ((m/ap
     (m/?< input)
     (try (loop []
            (m/amb (m/? m/never)
              (recur)))
          (catch Cancelled _
            (m/amb))))
   #(prn :ready) #(prn :done)))
(i! :a)
(i! :b)                                                   ;; infinite loop

The bug trace down to the infinite loop when itering over Processor (when there is only one Processor, it loops infinitely).

do pr = pr.next; while (pr.prev == null);

And also, there are two more while loops like that one. I may need to dig a little more to check if they're necessary to be checked. (itering branch in walk and itering choice in cancel). But I add the similar check anyway here)

I can submit a PR if that's acceptable.

I created branch ap-infinite-loops and pushed this failing test. You can submit PRs on this branch.

@lotuc thank you for tracing this issue. Your fix looks correct to me, I think it can be improved by moving the tail check before the do-while, to avoid re-traversing the entire circular linked list.

The other loops L166 L191 likely have the same issue, but I'd like to prove it with a test before applying the same treatment.