Page MenuHome

Undo system: Debug assert while undoing several operations
Closed, ResolvedPublicBUG

Description

System Information
Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: AMD FirePro W2100 ATI Technologies Inc. 4.5.13560 Core Profile Context FireGL 26.20.11024.6001

Blender Version
Broken: version: 2.90 (sub 0), branch: master, commit date: 2020-04-19 19:15, hash: rBa331d7990074
Worked: (newest version of Blender that worked as expected)

Short description of error
It appears as though there's some badness going on between selection, edit/object mode toggling, and perhaps modal operators? It's been very difficult to nail down for certain. What's below is the smallest repro I've been able to reliably hit the assert.

Exact steps for others to reproduce the error

  • Start with default scene
  • Duplicate+Move the cube to the side
  • Select original cube
  • Select duplicated cube (don't shift select, just select normally)
  • Toggle edit mode
  • Subdivide
  • (De) Select all
  • Hit 3 to do Face select
  • Box select 4 faces of the cube
  • E then S to extrude then scale
  • Enable the Transform gizmo
  • Move the already selected faces
  • Toggle object mode
  • Ctrl-Z as far back as you can go

BLI_assert failed: F:\source\blender-git\blender\source\blender\blenlib\intern\BLI_ghash.c:462, ghash_insert_ex(), at '(gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)'

Taken with --debug-io --log "*"

Undo 13 Steps (*: active, #=applied, M=memfile-active, S=skip)
[ #  ]   0 {000001505A7C7A18} type='Global Undo', name='Original'
[ #  ]   1 {00000150043DB0D8} type='Global Undo', name='Duplicate Objects'
[ #  ]   2 {00000150043DE018} type='Global Undo', name='Select'
[*#M ]   3 {00000150043DE858} type='Global Undo', name='Select'
[    ]   4 {00000150043DFB18} type='Edit Mesh', name='Toggle Editmode'
[    ]   5 {00000150043DEA98} type='Edit Mesh', name='Subdivide'
[    ]   6 {00000150043DFE18} type='Edit Mesh', name='(De)select All'
[    ]   7 {00000150043DFC98} type='Edit Mesh', name='Select Mode'
[    ]   8 {00000150043DE9D8} type='Edit Mesh', name='Box Select'
[    ]   9 {00000150043DEB58} type='Edit Mesh', name='Extrude Region and Move'
[    ]  10 {00000150043DF458} type='Edit Mesh', name='Transform Gizmo Set'
[    ]  11 {00000150043DEE58} type='Edit Mesh', name='Move'
[    ]  12 {00000150043DDE98} type='Global Undo', name='Toggle Editmode'
INFO (wm.operator): F:\source\blender-git\blender\source\blender\windowmanager\intern\wm_event_system.c:857 wm_operator_reports: bpy.ops.ed.undo()
Info: Checking sanity of current .blend file *BEFORE* undo step
Info: Checking sanity of current .blend file *AFTER* undo step

INFO (wm.operator): F:\source\blender-git\blender\source\blender\windowmanager\intern\wm_operators.c:794 WM_operator_last_properties_store: storing properties for 'ED_OT_undo'
INFO (wm.operator): F:\source\blender-git\blender\source\blender\windowmanager\intern\wm_operators.c:739 operator_last_properties_init_impl: loading previous properties for 'ED_OT_undo'
INFO (ed.undo): F:\source\blender-git\blender\source\blender\editors\undo\ed_undo.c:119 ed_undo_step_impl: name='(null)', step=1
INFO (bke.undosys): F:\source\blender-git\blender\source\blender\blenkernel\intern\undo_system.c:676 BKE_undosys_step_undo_with_data_ex: addr=00000150043DE018, name='Select', type='Global Undo'
34: BLI_system_backtrace - 0x7FF78A048A20
33: ghash_insert_ex - 0x7FF78A06B340
32: ghash_insert - 0x7FF78A06B280
31: BLI_ghash_insert - 0x7FF78A068300
30: view_layer_bases_hash_create - 0x7FF781270820
29: BKE_layer_collection_sync - 0x7FF78126B400
28: BKE_scene_collection_sync - 0x7FF78126BF60
27: BKE_main_collection_sync - 0x7FF78126BA60
26: BKE_collections_after_lib_link - 0x7FF7812FC510
25: blo_read_file_internal - 0x7FF78168FB00
24: BLO_read_from_memfile - 0x7FF7816D23B0
23: BKE_blendfile_read_from_memfile - 0x7FF78B1D8860
22: BKE_memfile_undo_decode - 0x7FF78B237FA0
21: memfile_undosys_step_decode - 0x7FF7826067E0
20: undosys_step_decode - 0x7FF78B1D7A70
19: BKE_undosys_step_undo_with_data_ex - 0x7FF78B1D6580
18: BKE_undosys_step_undo_with_data - 0x7FF78B1D6500
17: BKE_undosys_step_undo - 0x7FF78B1D6310
16: ed_undo_step_impl - 0x7FF782609CE0
15: ed_undo_step_direction - 0x7FF782609C60
14: ed_undo_exec - 0x7FF7826095E0
13: wm_operator_invoke - 0x7FF78163B8C0
12: wm_handler_operator_call - 0x7FF781636CE0
11: wm_handlers_do_keymap_with_keymap_handler - 0x7FF781639F00
10: wm_handlers_do_intern - 0x7FF781639260
9: wm_handlers_do - 0x7FF781637D00
8: wm_event_do_handlers - 0x7FF7816328B0
7: WM_main - 0x7FF781609030
6: main - 0x7FF780E7F130
5: invoke_main - 0x7FF78B1C8F40
4: __scrt_common_main_seh - 0x7FF78B1C8CF0
3: __scrt_common_main - 0x7FF78B1C8CD0
2: mainCRTStartup - 0x7FF78B1C9000
1: BaseThreadInitThunk - 0x7FFFA7317BC0
0: RtlUserThreadStart - 0x7FFFA910CE30
BLI_assert failed: F:\source\blender-git\blender\source\blender\blenlib\intern\BLI_ghash.c:462, ghash_insert_ex(), at '(gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)'

Event Timeline

couldn't redo on rB5cc7e2ae16d47c58f4a560efaf3a3a35eafe1352
is there a hidden setting I forgot to change for undo ?

I can still reproduce as of rB9618bd9202a

If it doesn't trigger the first time, can you try running through the steps a second time using the same scene.

Crashed for me on the first try but not the second. Investigating.

Undo 12 Steps (*: active, #=applied, M=memfile-active, S=skip)
[ #  ]   0 {000001EB71D48868} type='Global Undo', name='Original'
[ #  ]   1 {000001EB71D4A368} type='Global Undo', name='Duplicate Objects'
[*#M ]   2 {000001EB71D49D68} type='Global Undo', name='Select'
[    ]   3 {000001EB71D4A128} type='Global Undo', name='Select'
[    ]   4 {000001EB71D49EE8} type='Edit Mesh', name='Toggle Editmode'
[    ]   5 {000001EB676E0FA8} type='Edit Mesh', name='Subdivide'
[    ]   6 {000001EB676DFF28} type='Edit Mesh', name='(De)select All'
[    ]   7 {000001EB676DEDE8} type='Edit Mesh', name='Select Mode'
[    ]   8 {000001EB676DE7E8} type='Edit Mesh', name='Box Select'
[    ]   9 {000001EB676DE668} type='Edit Mesh', name='Extrude Region and Move'
[    ]  10 {000001EB676E05E8} type='Edit Mesh', name='Move'
[    ]  11 {000001EB676DF628} type='Global Undo', name='Toggle Editmode'
INFO (wm.operator): C:\blender-git\blender\source\blender\windowmanager\intern\wm_event_system.c:857 wm_operator_reports: bpy.ops.ed.undo()
Info: Checking sanity of current .blend file *BEFORE* undo step
Info: Checking sanity of current .blend file *AFTER* undo step

INFO (wm.operator): C:\blender-git\blender\source\blender\windowmanager\intern\wm_operators.c:794 WM_operator_last_properties_store: storing properties for 'ED_OT_undo'
Error   : EXCEPTION_ACCESS_VIOLATION
Address : 0x00007FF65B41DA4D
Module  : C:\blender-git\build_windows_x64_vc16_Release\bin\Release\blender.exe

55a2682348df

Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: GeForce GTX 470/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 376.51

I have been able to reproduce on both a release build and a debug build running in debug mode. It happens when I start up with my default scene using various --debug commands in the CLI, and then load factory defaults from the menu. I haven't gotten it to occur when I use --factory-startup in combination with --debug from the command line.

The assert was added by @Campbell Barton (campbellbarton) back in 2013. rBfbb446dff620

only checked for in debug mode

@Richard Antalik (ISS) @Ankit Meel (ankitm) are you running in debug mode, and are you using factory startup?

Evan Wilson (EAW) changed the task status from Needs Triage to Confirmed.Apr 21 2020, 4:52 AM

I have been able to reproduce on both a release build and a debug build running in debug mode. It happens when I start up with my default scene using various --debug commands in the CLI, and then load factory defaults from the menu. I haven't gotten it to occur when I use --factory-startup in combination with --debug from the command line.

The assert was added by @Campbell Barton (campbellbarton) back in 2013. rBfbb446dff620

only checked for in debug mode

@Richard Antalik (ISS) @Ankit Meel (ankitm) are you running in debug mode, and are you using factory startup?

I probable wasn't able to reproduce, because I haven't run with any --debug argument.

Ankit Meel (ankitm) added a comment.EditedApr 21 2020, 3:11 PM

are you running in debug mode, and are you using factory startup?

earlier no, now I tried that. but couldn't redo. --debug-io

can you try running through the steps a second time using the same scene.

Then did this, to get three cubes, couldn't redo.

then did some cycles of cmd + Z to get original scene and then cmd + shift + z to get final scene. After some such cycles, got the trace as in the report.

Bastien Montagne (mont29) changed the subtype of this task from "Report" to "Bug".
Bastien Montagne (mont29) moved this task from Backlog to bcon3: Bugs on the BF Blender (2.83) board.
Bastien Montagne (mont29) moved this task from Backlog to Bugs on the Pipeline, Assets & I/O board.

Very hard to reproduce for me, even more in debug builds... This is related to adding/removing objects, for some reasons once in a while 'things' get corrupted in the Object/Collection area. It can then trigger that assert or not, or crash in the collection update code, or in CoW code in depsgraph, or...

Managed to get it crash with -t 1 so don't think this is a threading issue.

I haven't been able to reproduce this problem, so this is just speculation.

From the backtrace and steps to redo, I think somehow we end up in a situation where two bases point to the same object, which triggers the ghash assert. This seems at least not caused by depsgraph or recalc flags, as the collection sync has the problem on original data.

I would guess that somehow fd->libmap ends up mapping two different pointers to the same object. This would mean either the wrong object is found by undo restore (duplicate session ID, some issue in old_idmap, ..). Or there is something wrong with the way we construct or use fd->libmap.

What I still find odd in the undo restore code is putting the current ID pointer in there. Maybe this can end up being the same as another bhead->old value? Things still seem to work correctly without it, and I'm not sure why it is needed.

So for those who can reproduce, it would be good if this patch can be tested. Even if it's wrong it might give a clue.

--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9713,9 +9713,8 @@ static bool read_libblock_undo_restore(
     read_libblock_undo_restore_identical(fd, main, id, id_old, id_tag);
 
     /* Insert into library map for lookup by newly read datablocks (with pointer
-     * value bhead->old) or existing datablocks in memory (pointer value id_old). */
+     * value bhead->old). */
     oldnewmap_insert(fd->libmap, bhead->old, id_old, bhead->code);
-    oldnewmap_insert(fd->libmap, id_old, id_old, bhead->code);
 
     *r_id_old = id_old;
     return true;
@@ -9787,10 +9786,9 @@ static BHead *read_libblock(FileData *fd,
   BLI_addtail(lb, id);
 
   /* Insert into library map for lookup by newly read datablocks (with pointer
-   * value bhead->old) or existing datablocks in memory (pointer value id_old). */
+   * value bhead->old). */
   ID *id_target = id_old ? id_old : id;
   oldnewmap_insert(fd->libmap, bhead->old, id_target, bhead->code);
-  oldnewmap_insert(fd->libmap, id_old, id_target, bhead->code);
 
   if (r_id) {
     *r_id = id_target;

@Brecht Van Lommel (brecht) i think you nailed it. At lest when removing those two lines I cannot reproduce any crash anymore, while with current code and file attached below it is fairly easy (just duplicate a few times the whole selection of objects, and undo/redo, usually crashes fairly quickly for me).

I'd like to rethink this tomorrow with a fresh head though, want to recheck the cases where those would/could be needed again...

Ankit Meel (ankitm) added a comment.EditedApr 22 2020, 9:40 AM

Was testing this with the details given in #914819 when I got this error while doing undo redo cycles:

Traceback (most recent call last):
  File "/Users/ankitkumar/blender-build/build/bin/Debug/Blender.app/Contents/Resources/2.90/scripts/startup/bl_ui/properties_object.py", line 61, in draw
    row.prop(ob, "location")
TypeError: UILayout.prop(): error with argument 1, "data" -  Function.data does not support a 'None' assignment AnyType type

location: <unknown location>:-1

location: <unknown location>:-1
Traceback (most recent call last):
  File "/Users/ankitkumar/blender-build/build/bin/Debug/Blender.app/Contents/Resources/2.90/scripts/startup/bl_ui/space_view3d.py", line 55, in draw
    VIEW3D_HT_header.draw_xform_template(layout, context)
  File "/Users/ankitkumar/blender-build/build/bin/Debug/Blender.app/Contents/Resources/2.90/scripts/startup/bl_ui/space_view3d.py", line 560, in draw_xform_template
    object_mode = 'OBJECT' if obj is None else obj.mode
AttributeError: 'Image' object has no attribute 'mode'

location: <unknown location>:-1

location: <unknown location>:-1
Traceback (most recent call last):
  File "/Users/ankitkumar/blender-build/build/bin/Debug/Blender.app/Contents/Resources/2.90/scripts/startup/bl_ui/space_view3d.py", line 675, in draw
    object_mode = 'OBJECT' if obj is None else obj.mode
AttributeError: 'Image' object has no attribute 'mode'

location: <unknown location>:-1

location: <unknown location>:-1

Also, can confirm that applying the patch stops crashes in both, the file "undo_redo_crash_ID_creation.blend" & the original steps with the modifications in #914819

Yeah, in fact those mapping entries were needed when we were still lib-linking the whole set of data-blocks. Now we are only ever lib-linking IDs that were actually re-read during that undo step, so we can get rid of those (and avoid the conflicting memory addresses caused by repetitive re-allocations that will happen when undoing/redoing IDs addition/deletion.