koka-lang / koka

Koka language compiler and interpreter
http://koka-lang.org
Other
3.16k stars 151 forks source link

Segfault in compiled program #462

Open chtenb opened 4 months ago

chtenb commented 4 months ago

I was experimenting with some parser code while I hit a segfault. I was not able to shrink the reproduction unfortunately. I've added a few debugging statements which are hopefully helpful. The output of the program is:

next
tokenize
parse-tsv-value
many1
none-of
token-is
satisfy-fail
satisfy
next
failure during program run:
   ".koka/v3.0.5/clang-cl-debug/interactive"

Since github shows the entire block of code verbatim in this post, I've created a gist for the reproduction code: https://gist.github.com/chtenb/35410c6c66581cf5fd81ff1be697da9a

TimWhiting commented 4 months ago

Try changing

pub fun debug(msg : string) : total ()
  unsafe-total({println(msg)})

to

pub fun debug(msg : string) : total ()
  trace(msg)

unsafe-total is really unsafe :)

Sorry, just realized that gets you a bit further but there is still a segfault

TimWhiting commented 4 months ago

It seems that the continuation context escapes it's scope in the iter method, and the resumption isn't valid for whatever reason. This is definitely a bug, though I'm not certain whether it should be a type error or there is something not being handled properly in the effect runtime. I think normally I would suggest changing the ctl clause to raw ctl, but that doesn't seem to fix it either.

chtenb commented 4 months ago

Thanks for your response. Good to know that the trace function is safer to use than my custom debug function.

daanx commented 4 months ago

Ah this is indeed a real bug :-( -- I tried to run with --target=js and also got an error. Strange -- it might be that it is ill-typed but the type checker doesn't pick up on it.. or (more likely) a "simplification/optimization" that gets the monadic translation wrong or something. Tricky -- I'll try to spend more time on it later this week. tbc

daanx commented 4 months ago

Maybe it has to do with the mask in many... I see the typing is quite tricky there, interesting :-)

TimWhiting commented 4 months ago

The resume function escapes the handler. Is that supported? The compiler builds up a resumption for general ctl operations, but I was unaware whether it includes in the resumption a Deep resumption reinstalling the handler if it has escaped the handler's scope.

daanx commented 4 months ago

Ah yes -- it should be written as:

raw ctl yield(a)
   Just( (a, Iter(fn() rcontext.resume(()) )) )

(.. but if you forget this there should be an error message at runtime). However, even with this change the program still crashes, it must be something else -- I think it happens earlier? Btw. The raw ctl is needed as the standard one assumes that resume does not escape and can then guarantee that all finalizers will run. In contrast, a raw ctl does not do this -- you may need to call rcontext.finalize to run finalizers in the resumption eventually.

TimWhiting commented 4 months ago

Unlikely to be the same issue, but https://github.com/koka-lang/koka/issues/360 also relates to the effect handler runtime.