ID:1959087
 
Resolved
Saving large lists of items (particularly turfs) rather than saving one at a time could cause a stack overflow in some cases.
BYOND Version:509.1305
Operating System:Windows 7 Ultimate 64-bit
Web Browser:Chrome 45.0.2454.101
Applies to:Dream Daemon
Status: Resolved (509.1306)

This issue has been resolved.
Code Snippet (if applicable) to Reproduce Problem:
mob
verb
WorkingSaveMap()
var/list/l = block(locate(1,1,1),locate(32,32,1))
var/savefile/F = new("test.sav")
F << l
BrokenSaveMap()
var/list/l = block(locate(1,1,1),locate(32,32,1))
for(var/count in 1 to 1024)
new/obj(l[count])
var/savefile/F = new("test.sav")
F << l

//comment the rest out to confirm that it works completely fine
turf
Write(savefile/F)
..()


BrokenSaveMap() crashes out with an infinite recursion. The default action of turf/Write seems to break everything.
Descriptive Problem Summary:

When saving a large number of objects, Write() claims absurd values in the CPU profiler. When saving 1024 turfs, the Self CPU read as 21878.064, while the total CPU read 19.342, and real time was 19.343. Yet the function that called the Write() claims only 0.007 self CPU and 0.125 total CPU.


Code Snippet (if applicable) to Reproduce Problem:
world
fps = 25 // 25 frames per second
icon_size = 32 // 32x32 icon size by default

view = 6 // show up to 6 tiles outward from center (13x13 view)
turf = /turf/subturf


var
chunk/operation_chunk

chunk
var
x
y
z
width
height
depth
tmp
offset_load = 0
x_offset = 0
y_offset = 0
z_offset = 0
proc
Save(filename)
while(operation_chunk)
sleep(world.tick_lag)
var/savefile/F = new/savefile(filename)
operation_chunk = src
try
F << src
F << block(locate(x,y,z),locate(x+width-1,y+height-1,z+depth-1))
catch(var/exception/e)
world.log << "[e.file] [e.line]: [e]"
operation_chunk = null

Load(filename)
while(operation_chunk)
sleep(world.tick_lag)
var/savefile/F = new/savefile(filename)
operation_chunk = src
try
var/chunk/c , list/l
F >> c
F >> l
catch(var/exception/e)
world.log << "[e.file] [e.line]: [e]"
operation_chunk = null
if(offset_load)
offset_load = 0
x_offset = 0
y_offset = 0
z_offset = 0

New(x,y,z,width,height,depth)
src.x = x
src.y = y
src.z = z
src.width = width
src.height = height
src.depth = depth

Read(savefile/F)
..()
if(x!=operation_chunk.x||y!=operation_chunk.y||z!=operation_chunk.z)
operation_chunk.offset_load = 1
operation_chunk.x_offset = operation_chunk.x-x
operation_chunk.y_offset = operation_chunk.y-y
operation_chunk.z_offset = operation_chunk.z-z

Write(savefile/F)
..()

turf
subturf
New()
new/obj(src)

Write(savefile/F)
..()

obj

atom/movable
var
chunk_save = 1
Write(savefile/F)
if(operation_chunk&&(!chunk_save||x<operation_chunk.x||y<operation_chunk.y)) return
..()

turf

mob
Login()
//chunk_save = 0
..()

Stat()
stat("cpu:",world.cpu)

verb
save_chunk()
var/chunk/c = new/chunk(1,1,1,32,32,1)
world.log << "this message shows"
c.Save("test.sav")
world.log << "this message does not"
c.Load("test.sav")
Descriptive Problem Summary:

Lummox, something has happened to savefiles. You have no idea how many bugs I've run into in the last several minutes. I've got another one for you.

The function that calls the save function utterly fails to call the load function at all. See the lack of messages after Save() is called on the chunk object.

Code Snippet (if applicable) to Reproduce Problem:
world
fps = 25 // 25 frames per second
icon_size = 32 // 32x32 icon size by default

view = 6 // show up to 6 tiles outward from center (13x13 view)
turf = /turf/subturf


var
chunk/operation_chunk

chunk
var
x
y
z
width
height
depth
tmp
offset_load = 0
x_offset = 0
y_offset = 0
z_offset = 0
proc
Save(filename)
while(operation_chunk)
sleep(world.tick_lag)
var/savefile/F = new/savefile(filename)
operation_chunk = src
try
F << src
F << block(locate(x,y,z),locate(x+width-1,y+height-1,z+depth-1))
catch(var/exception/e)
world.log << "[e.file] [e.line]: [e]"
operation_chunk = null

Load(filename)
while(operation_chunk)
sleep(world.tick_lag)
var/savefile/F = new/savefile(filename)
operation_chunk = src
try
var/chunk/c , list/l
F >> c
F >> l
catch(var/exception/e)
world.log << "[e.file] [e.line]: [e]"
operation_chunk = null
if(offset_load)
offset_load = 0
x_offset = 0
y_offset = 0
z_offset = 0

New(x,y,z,width,height,depth)
src.x = x
src.y = y
src.z = z
src.width = width
src.height = height
src.depth = depth

Read(savefile/F)
..()
if(x!=operation_chunk.x||y!=operation_chunk.y||z!=operation_chunk.z)
operation_chunk.offset_load = 1
operation_chunk.x_offset = operation_chunk.x-x
operation_chunk.y_offset = operation_chunk.y-y
operation_chunk.z_offset = operation_chunk.z-z

Write(savefile/F)
..()

turf
subturf
New()
new/obj(src)

Write(savefile/F)
..()

obj

atom/movable
var
chunk_save = 1
Write(savefile/F)
if(operation_chunk&&(!chunk_save||x<operation_chunk.x||y<operation_chunk.y)) return
..()

turf

mob
Login()
//chunk_save = 0
..()

Stat()
stat("cpu:",world.cpu)

verb
save_chunk()
var/chunk/c = new/chunk(1,1,1,32,32,1)
world.log << "this message shows"
c.Save("test.sav")
world.log << "this message does not"
c.Load("test.sav")
In response to Ter13
I'll look into this and the other issues and see what I can find. Can you narrow down a version where any of this started happening?
In response to Ter13
I can do that. Let me finish what I'm doing and then I'll get right on it.
Lummox JR resolved issue with message:
Saving large lists of items (particularly turfs) rather than saving one at a time could cause a stack overflow in some cases.
In response to Ter13
I think this might be identical to the issue you reported in id:1959087. Some code handling a routine that could be reentered was not actually performing all that nicely, and as a result it was causing stack overflow.
In response to Ter13
Stack overflow is likely the cause of this issue as well.