ID:2349322
 
Resolved
Attempting to animate a bogus object, or an abstract filter() not attached to an object, did not result in a runtime error. It could however result in a crash in some cases.
BYOND Version:512.1411
Operating System:Linux
Web Browser:Chrome 63.0.3239.132
Applies to:Dream Daemon
Status: Resolved (512.1413)

This issue has been resolved.
Descriptive Problem Summary:
Animating an object's transform while using filters to animate the object concurrently causes the hosting process to crash.

Numbered Steps to Reproduce Problem:
1) Use this test environemnt or the source below
2) Use the CreateObj() verb until the process crashes
Code Snippet (if applicable) to Reproduce Problem:
world
fps = 25 // 25 frames per second
icon_size = 32 // 32x32 icon size by default
maxx=5
maxy=5
maxz=1
view = 6 // show up to 6 tiles outward from center (13x13 view)

atom/var/tmp/dashFilter
atom/icon = 'test.dmi'
turf/icon_state = "turf"
mob
verb
/**
* Using this verb several times will reproduce the conditions that
* caused the crash. For reasons I do not know, the bug does not always
* occur when the verb is invoked. However, using it several times
* seems to reliably trigger a crash.
*/

CreateObj()
var/obj/o = new(loc)
o.AnimationCrash()

obj
proc
AnimationCrash()
dashFilter = filter(type="motion_blur", x=3, y=1, loop=-1)
filters = dashFilter
animate(dashFilter, time=2)
// The bug only seems to manifest while motion blurred object is
// animated to spin
var/willSpin = TRUE
if(willSpin)
var/t = 1
var/savedTransform = src.transform
animate(src, transform = turn(savedTransform, 120), time = t, loop = -1)
animate(transform = turn(savedTransform, 240), time = t)
animate(transform = savedTransform, time = t)
sleep(2)
animate(dashFilter, x=0, y=0, time=2)
sleep(2)
filters=null // Commenting out this line seems to stop the crash
// Remove the objects from the screen
sleep(10)
del(src)


Expected Results:
A motion blurred spinning object
Actual Results:
A motion blurred spinning object that tends to crash Dream Daemon
Does the problem occur:
Every time? Or how often?
It seems to occur after a random number of times the AnimationCrash() is invoked.
In other games?
The above code is an isolated code snippet from a larger project.
In other user accounts?
On other computers?
I've tested this running on an Ubuntu Virtual Machine and on Windows 10 Home Edition. Neither environment prevents Dream Daemon from crashing in those cases. The Ubuntu VM sometimes provides the following error message:
BUG: Crashing due to an illegal operation!

However, this error message does not always appear. Sometimes the process will hang until killed.
When does the problem NOT occur?
The problem does not seem to occur when the obj is not animated to spin or when the filters list is not set to null.
Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)

Workarounds:

I was able to reproduce your crash and will get to work on fixing it.

Your code however is broken. There are two problems. First, loop is not a valid argument to filter(); it's an animation argument. Second, calling animate() on dashFilter won't work, because it's a raw filter and isn't assigned to any object. The way to animate the filter is to call animate() on filters[1], which references the first filter belonging to src.

I believe that calling animate() with the correct argument will eliminate your crash. Obviously I still have a bug to fix though.
Lummox JR resolved issue with message:
Attempting to animate a bogus object, or an abstract filter() not attached to an object, did not result in a runtime error. It could however result in a crash in some cases.
In the new version, your code will produce a runtime error: "Cannot animate abstract filter".

If you add this line immediately after setting filters = dashFilter, your code will work:

dashFilter = filters[1]  // now dashFilter points to src.filters[1] instead of an abstract

When you first create dashFilter, it's an abstract filter because it doesn't belong to any specific object. Assigning it to src.filters doesn't change that, because dashFilter is still abstract and can be assigned to another object. Animating this abstract filter would have no meaning.

src.filters[1] on the other hand is tied to src. You can animate it just fine, because it belongs to an object.