encore
encore copied to clipboard
Programs exit instead of blocking when cyclic dependency exists.
Hello! I have found an odd bug.
This is only tested for the new-ponyrt
branch.
Some encore programs terminate prematurely. The program doesn't crash it just exits successfully.
For example the following program
class Main
def main() : void {
let
boo = new Boo
far = new Far
in{
print "main start";
far = new Far(boo);
print "main middle";
get far.bar();
print "main end";
}
}
class Boo
def foo(far : Far) : int{
print "foo start";
let
a = get far.getSilly()
in{
print "foo end";
a
}
}
class Far
boo : Boo
silly : int
def init(boo : Boo) : void {
print "Far init start";
this.boo = boo;
this.silly = embed int rand(); end;
print "Far init end";
}
def bar() : void{
print "bar start";
let
lol = this.boo.foo(this)
in{
print "bar midle";
print get lol;
print "bar end";
}
}
def getSilly() : int{
print "get silly start";
this.silly;
}
Produces the following output when run in gdb
:
[New Thread 0x7ffff5ff6700 (LWP 11947)]
main start
main middle
Far init start
Far init end
bar start
bar midle
foo start
[New Thread 0x7ffff57f5700 (LWP 11948)]
[New Thread 0x7ffff37f4700 (LWP 11949)]
[Thread 0x7ffff37f4700 (LWP 11949) exited]
[Thread 0x7ffff57f5700 (LWP 11948) exited]
[Thread 0x7ffff5ff6700 (LWP 11947) exited]
[Inferior 1 (process 11943) exited normally]
So the program shuts down prematurely. I know that the program contains a deadlock and its behavior is thus a bit iffy.
I have done some forensic and pinpointed the error too:
int ret = swapcontext(&ctx, &this_context->ctx);
at line 190
in encore.c.
According to the the internet and the man pages. swapcontext
/setcontext
can cause the program to prematurely exit successfully.
Also, according to the man pages:
SUSv2, POSIX.1-2001. POSIX.1-2008 removes the specifications of makecontext() and swapcontext(), citing portability issues, and recommending that applications be rewritten to use POSIX threads instead.
I have only tested this on Linux so it might be a portability issue.
Using the head of new-ponyrt
, this is my output on linux:
main 10
main 12
Far init start
Far init end
bar start
bar midle
foo start
@albertnetymk my bad i changed the printouts after I copy pasted the code. But you run osx right
@TheGrandmother My laptop is mac air, but I run the above example using linux via ssh.
@albertnetymk Oki. Can you test it on osx?
in Mac:
(encore)➜ threadring git:(brussels) ✗ encorec -run test.enc
main 10
main 12
Far init start
Far init end
bar start
bar midle
foo start
@kikofernandez Oki then it's not just a Linux thing.
@TheGrandmother There seems one circular dependency: main -> far -> boo -> far. Hope I understand the program logic right.
@albertnetymk Yes there is a cyclic dependency. I found the bug when I was experimenting with deadlocks.
Currently, encore doesn't handle cyclic dependency, so you need to enforce it yourself for now.
@TheGrandmother It's probably good to change the title of this issue, for we know the reason why the program exits prematurely. Maybe sth like this: 'Programs exit instead of blocking when cyclic dependency exists.'?
What is the status of this?
It's captured in my last comment. To my knowledge, it's not decided what's the behavior encountering cyclic dependency, so the program just exits.
I believe the decision was to deadlock, but maybe you can take 5 minutes on Friday to talk about this and we can resolve it?