{"action":"created","issue":{"url":"https://api.github.com/repos/KSP-KOS/KOS/issues/707","labels_url":"https://api.github.com/repos/KSP-KOS/KOS/issues/707/labels{/name}","comments_url":"https://api.github.com/repos/KSP-KOS/KOS/issues/707/comments","events_url":"https://api.github.com/repos/KSP-KOS/KOS/issues/707/events","html_url":"https://github.com/KSP-KOS/KOS/issues/707","id":65633963,"number":707,"title":"Bug that broke @ziw's big script: can't have two idential wait expressions in two script files that call each other.","user":{"login":"Dunbaratu","id":5216848,"avatar_url":"https://avatars.githubusercontent.com/u/5216848?v=3","gravatar_id":"","url":"https://api.github.com/users/Dunbaratu","html_url":"https://github.com/Dunbaratu","followers_url":"https://api.github.com/users/Dunbaratu/followers","following_url":"https://api.github.com/users/Dunbaratu/following{/other_user}","gists_url":"https://api.github.com/users/Dunbaratu/gists{/gist_id}","starred_url":"https://api.github.com/users/Dunbaratu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Dunbaratu/subscriptions","organizations_url":"https://api.github.com/users/Dunbaratu/orgs","repos_url":"https://api.github.com/users/Dunbaratu/repos","events_url":"https://api.github.com/users/Dunbaratu/events{/privacy}","received_events_url":"https://api.github.com/users/Dunbaratu/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/KSP-KOS/KOS/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-04-01T08:41:55Z","updated_at":"2015-04-02T00:21:43Z","closed_at":null,"body":"This is a really weird, specific bug that took ages to track down.  I'm sleepy but I want to get the description exactly correct while its still fresh in my head, before I forget it.\r\n\r\n**To trigger the bug:**\r\nYou have one script that does these things in this order:\r\n  - Lock throttle to anything, even just ```lock throttle to 0.```  (*this probably also happens with lock steering too, but lock throttle is easier to test.**)\r\n  - Then execute a ```wait until <foo>.``` statement, for some expression <foo>, that can be anything.  Just make sure it's a ```wait until``` expression, rather than a raw ```wait <N>.``` to wait N seconds.\r\n  - Then run a second script from within this first script.\r\n\r\nYou have the second \"inner\" script that it runs do this:\r\n  - Execute a ```wait until <foo>.``` that uses **precisely the same expression** as the one in the first script.  It's essential that it is the exact same expression, such that it would compile into an identical list of opcodes to evaluate it.\r\n  - that should do it.  It should barf right there.\r\n\r\nThe error you'll get is \"random\" (not really random, it is deterministic, but differs depending on stuff not entirely under your control.  It will however be the *same* error each time you run the *same* exact code.)\r\n\r\nThe error is reported with bogus trace information, and it may cause stack misalignment too.  The actual error is that when the Update() attempts to run through updating the the flight control variables (like the $throttle* lock function) , it will end up executing an OpcodeCall that jumps to some other wrong part of the code instead of into the lock expression.  How many instructions offset the jump is from where it should be will depend on exactly how many instructions it takes to calculate the expression <foo>.  When the <foo> code was inserted up near the top where the trigger conditions go, the jump addresses for the throttle OpcodeCall never got updated to reflect this shift.  The IP location it refers to will be some other part of the program that got shifted down to that location.\r\n\r\nThis can cause stack misalignments, random re-running of statements that already completed, you name it - thus why the exact error is seemingly \"random\".\r\n\r\nThe bug *requires* that the two *wait until* statements be using *exactly* the same expression, or it will not trigger, which is a big clue as to where the problem is.\r\n\r\n__Where the problem probably is:__\r\nIn the compiler, there appears to be some logic that makes a hashcode number out of the list of opcodes that form the trigger conditional expression, and uses that hashcode to decide if it has already compiled this trigger once before.  Given that the bug only appears when you have the same exact condition in both waits, in two different scripts one that calls the other, that's probably where the problem is.\r\n\r\nI originally thought this problem was caused by my functions revamp, because it was my new wrong-nuber-of-args check in OpcodeReturn that was getting thrown.  But after a lot of analysis it turns out that my functions stuff was the \"victim\" of the problem, not the cause of it.  By jumping a few instructions ahead of where it was supposed to in the code, some of the \"pushes\" were skipped over, thus making the number of arguments wrong and triggering my message.\r\n\r\nThis bug was always there, and ziw reports that an error happened even before updating to the functions branch, but it was just a different error message.  (of course, this new exception didn't exist yet, so some other part of the system was offended by the problem of the call to the wrong location).\r\n\r\nHere's an example pair of scripts to run that trigger the bug:\r\n\r\nfile: testbug.ks:\r\n```\r\n// attempt to create the bug with a less complex test.\r\n\r\nlock throttle to 0.\r\nlock steering to up.\r\n\r\nprint \"testbug. waiting 2 seconds with a WAIT UNTIL\".\r\nset two_seconds_later to time:seconds + 2.\r\nwait until time:seconds > two_seconds_later.\r\nprint \"calling testbug_first.\".\r\nrun testbug_first.\r\nprint \"done\".\r\n```\r\n\r\nfile: testbug_first.ks\r\n```\r\nset aa to 0.5.\r\nset bb to 0.7.\r\nprint \"RUNNING testbug_first\".\r\nprint \" \".\r\nprint \"Leaving throttle locked at old value at first.\".\r\nprint \"Waiting 2 seconds with the use of a WAIT UNTIL,\".\r\nprint \"then I will lock throttle to a new value\".\r\nset two_seconds_later to time:seconds + 2.\r\nwait until time:seconds > two_seconds_later.\r\nprint \"wait done, locking throttle.\". // probably won't even get this far.\r\nlock throttle to (aa+bb)/2.\r\nprint \"done with inner\".\r\n```\r\n\r\nExample of running:\r\n```\r\nrun testbug.\r\ntestbug. waiting 2 seconds with a WAIT UNTIL\r\ncalling testbug_first.\r\nRUNNING testbug_first\r\n\r\nLeaving throttle locked at old value at first.\r\nWaiting 2 seconds with the use of a WAIT UNTIL,\r\nthen I will lock throttle to a new value\r\nwait done, locking throttle.\r\ndone with inner\r\nCannot cast from source type to destination type.\r\nAt testbug on archive, line 7\r\nset two_seconds_later to time:seconds + 2.\r\n                                      ^\r\n\r\n```\r\nIn the above example the totally bogus message was happening because where the ```lock throttle to 0.``` code still left in place from the first script was trying to jump to, the program code had been shifted down a bit and now in that same memory location was the OpcodeAdd from the expression, and it just jumped right to there and tried running from there, when it should have been jumping a bit further down in the program, to where the ```push 0. return.``` for the ```lock throttle to 0.``` got moved to.\r\n"},"comment":{"url":"https://api.github.com/repos/KSP-KOS/KOS/issues/comments/88673141","html_url":"https://github.com/KSP-KOS/KOS/issues/707#issuecomment-88673141","issue_url":"https://api.github.com/repos/KSP-KOS/KOS/issues/707","id":88673141,"user":{"login":"Dunbaratu","id":5216848,"avatar_url":"https://avatars.githubusercontent.com/u/5216848?v=3","gravatar_id":"","url":"https://api.github.com/users/Dunbaratu","html_url":"https://github.com/Dunbaratu","followers_url":"https://api.github.com/users/Dunbaratu/followers","following_url":"https://api.github.com/users/Dunbaratu/following{/other_user}","gists_url":"https://api.github.com/users/Dunbaratu/gists{/gist_id}","starred_url":"https://api.github.com/users/Dunbaratu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Dunbaratu/subscriptions","organizations_url":"https://api.github.com/users/Dunbaratu/orgs","repos_url":"https://api.github.com/users/Dunbaratu/repos","events_url":"https://api.github.com/users/Dunbaratu/events{/privacy}","received_events_url":"https://api.github.com/users/Dunbaratu/received_events","type":"User","site_admin":false},"created_at":"2015-04-02T00:21:42Z","updated_at":"2015-04-02T00:21:42Z","body":"I also just verified that the two duplicate WAIT's must be in *different* scripts to cause the bug.  If they're in the SAME script it's fine, like so:\r\n\r\ntestbug.ks:\r\n```\r\n// attempt to create the bug with a less complex test.\r\n\r\nlock throttle to 0.\r\nlock steering to up.\r\n\r\n// wait until, commented out from here:\r\n// print \"testbug. waiting 2 seconds with a WAIT UNTIL\".\r\n// set two_seconds_later to time:seconds + 2.\r\n// wait until time:seconds > two_seconds_later.\r\nprint \"calling testbug_first.\".\r\nrun testbug_first.\r\nprint \"done\".\r\n```\r\n\r\ntestbug_first.ks:\r\n```\r\nset aa to 0.5.\r\nset bb to 0.7.\r\n// wait until, moved to here instead, where it's in the same file as its duplicate:\r\nprint \"testbug. waiting 2 seconds with a WAIT UNTIL\".\r\nset two_seconds_later to time:seconds + 2.\r\nwait until time:seconds > two_seconds_later.\r\n\r\nprint \"RUNNING testbug_first\".\r\nprint \" \".\r\nprint \"Leaving throttle locked at old value at first.\".\r\nprint \"Waiting 2 seconds with the use of a WAIT UNTIL,\".\r\nprint \"then I will lock throttle to a new value\".\r\nset two_seconds_later to time:seconds + 2.\r\nwait until time:seconds > two_seconds_later.\r\nprint \"wait done, locking throttle.\". // probably won't even get this far.\r\nlock throttle to (aa+bb)/2.\r\nprint \"done with inner\".\r\n```\r\n\r\nThat variant works fine.  It MUST be that the duplicate waits are in two *different* scripts.\r\n\r\nGiven what I'm seeing in the compiler code, I wouldn't be surprised if WHEN/THEN and ON have the same exact problem.  It seems to affect all triggers of any type, and a WAIT UNTIL is technically a trigger too which is where it's getting the problem.\r\n"}}