ID:1772641
 
BYOND Version:507
Operating System:Windows Server 2012
Web Browser:Firefox 31.0
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
Upon using an href to manipulate a list for later construction via reading typepaths from various datums sometimes this error pops up and one of the list contents disappears.

runtime error: BYOND Error: bad datum
proc name: FindDesign (/datum/proc/FindDesign)
source file: designs.dm,96
usr: Emanuel Fea (/mob/living/carbon/human)
src: Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech)
call stack:
Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech): FindDesign()
Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech): add to queue()
Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech): add part set to queue("Robot", 7)
Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech): Topic("src=\[0x210f2678];queue_part_s...", /list (/list))
Exosuit Fabricator (/obj/machinery/r_n_d/fabricator/mech): Topic("src=\[0x210f2678];queue_part_s...", /list (/list))
/datum/nanoui (/datum/nanoui): Topic("src=\[0x210f2678];queue_part_s...", /list (/list))
Deusgero (/client): Topic("src=\[0x210f2678];queue_part_s...", /list (/list), /datum/nanoui (/datum/nanoui))
Some code night help.
/obj/machinery/r_n_d/fabricator/proc/convert_part_set(set_name as text)
var/list/parts = part_sets[set_name]
if(istype(parts, /list))
for(var/i=1;i<=parts.len;i++)
var/thispart = parts[i]
if(thispart && ispath(thispart) && !istype(thispart, /datum/design))
var/design = FindDesign(thispart)
if(design)
parts[i] = new design
else
parts.Cut(i, i++)
i--
You're still missing big swaths of code relevant to your report, and this proc isn't even part of that call stack. You're missing:

- client/Topic(), unless it's simply passing this on to the datum via ..() -- in which case the datum's Topic() is more relevant
- add_part_set_to_queue()
- add_to_queue()
- FindDesign()

The problem is showing up within FindDesign(), but I'm also very curious what's happening in the other procs in your call stack.

To be clear I do believe this is still a BYOND bug. I looked into how client/Topic() handles the lookup of "src" and it looks pretty darn solid in that it shouldn't create a reference to a missing datum. I did however discover that trying to update the refcount of a datum's vars list does not update the datum's refcount itself, as it should and as is the case for atoms. Hence why I think your missing source is highly relevant; it will tell us more about how the datum is being used.
Maybe i should not post or touch DM late at night.
http://puu.sh/fcdNn/5d08507d8b.txt
Is the fabricator code.
http://puu.sh/fcdT1/7368cad99e.txt
Is designs.dm

looking at the line in designs it shouldn't ever be passing an object, the designs are stored in datums and as typepaths, it used to be objects but we were getting issues with the references suddenly pointing to something else, so you'd attempt to make say a robot arm and you'd get a toolbox instead.
Here's something odd:

/datum/proc/FindDesign(var/part as anything)
if(!ispath(part))
var/obj/thispart = part
part = thispart.type
for(var/thisdesign in typesof(/datum/design))
var/datum/design/D = thisdesign
if(initial(D.build_path) == part)
return D
return

You're assigning a type path to D, not an instantiated datum. I suspect initial() is allowing the D.build_path to get through without complaining about how it can't read /datum/blah.build_path. The only way this proc could possibly work correctly would be to either instantiate such a datum on the fly, or keep an associative list. For instance:

var/list/design_paths
proc/DesignPath(t)
if(!design_paths) design_paths = new
. = design_paths[t]
if(!.)
var/datum/D = new t()
. = D.build_path
design_paths[t] = .

There's still a BYOND bug in play obviously, since the error message should be something different, although it's kind of a minor bug because at the end of the day, the proc is broken. I'm gonna move this to Bug Reports as it's unlikely to be beta-related. But if you find this kind of solution fixes your issue, then I'll know it's something about initial() that's causing the problem.

[edit]
Please put something other than "2012" as your operating system in bug reports. I don't know what that's supposed to mean.
Main issue we had with keeping a list that contained a 'memory' reference is we were getting collisions of some sort, like the GC was recycling the references in that list randomly, only way to fix it from doing that was to keep a list of type paths and instantiate the things when they were going to be built.
Also Sorry its windows server 2012
In response to Pomf123
Pomf123 wrote:
Main issue we had with keeping a list that contained a 'memory' reference is we were getting collisions of some sort, like the GC was recycling the references in that list randomly, only way to fix it from doing that was to keep a list of type paths and instantiate the things when they were going to be built.

There was a list bug in 506 and some early 507 builds that could have accounted for the problem you mentioned. But an instantiated list of objects is a better way to go, or you can simply instantiate them temporarily and have a list of their build_path values, as in my code above.
After making your suggested changes I haven't seen bad datum popup in the runtime logs yet. I'll update if it happens again though.