Values feed back into OUTPUT pin IO boxes

This was a real head scratcher. I could not for the life of me figure out why I was changing values in a patch, saving it, and when I re-ran my program the old values were back!

I have patches that I use to set a bunch of values, and they contain IO boxes that are outputs and have nothing connected to their inputs, values are just directly set in them to use as outputs, so I can set a bunch of data all in one place. I have found that even if I change those IO box values and save that patch, they still have their old values unless the including patch is saved also at the same time.

But when I load just the patch with the IOBoxes by itself, the changed values are there. Yet when loaded by the parent patch, the old values are back!

In the attached zip, first open IOBug-2.v4p, and note the order of values in the IOBox is 3,2,1. Now double-click and open IOBug-1.v4p, which includes IOBug-2.v4p, and see that the value not only being output by IOBug-2 is 1,2,3, but the IOBox inside IOBug-2 shows 1,2,3 as well.

You can click between the two instances of the IOBug-2 patch and see the values change! So the old values in IOBug-1 are actually feeding back into the OUTPUT of the child patch!

For extra fun, start vvvv fresh by double-clicking on IOBug-1.v4p. Go into IOBug-2.v4p and change a value. Quit vvvv, and save IOBug-2.v4p when prompted. Note you are not prompted to save IOBug-1.v4p. Rerun IOBug-1.v4p and there are the old values back in IOBug-2.v4p again.

But WAIT there’s MORE! Open patch 1, change a value in patch 2, and then exit but only save patch 1, not 2, where you changed the value. Rerun patch 1, and presto, the change is in patch 2. But not of course if you open patch 2 by itself.

Seriously FUBAR - who would think you need to save all the patches that contain a patch you’ve modified… PARTICULARLY when they are not flagged as needing to be saved.

This happens with 34.2_x64 and a 35.6 alpha.

IOBug.zip (1.2 KB)

hei mediadog,

please consult those two threads and see if they help understand your situation:

Thanks joreg for the pointers! Those help explain what is perhaps the mechanism underlying what I am seeing, but not the case that my example demonstrates where there is only one instance of the subpatch. The problem appears that information for the IOBoxes of a subpatch are being stored in the parent patch, regardless of how many instances of the subpatch there are. This leads to this clearly incorrect behavior:

  1. There is a subpatch that defines values statically, ie. set directly in the IOBox with no input connected.
  2. The subpatch is included only once in a parent patch.
  3. All the patches are saved.
  4. The values in the subpatch IOBox are changed.
  5. vvvv is exited, and the user is prompted to save the subpatch only (as expected).
  6. When the parent patch is re-run, the old values are back in the parent and subpatch.
  7. The ONLY way to get the expected behavior in all cases is to once again modify the values in the subpatch, and save BOTH it and the parent.

There is no way you can consider this anything but a bug. User intent and expectations are clearly being violated with no indication to the user as to why or that it will occur. It is an insidious and non-sensical behavior, as the effective values are obviously being stored in the parent, not in the subpatch.

What’s worse, if the subpatch is included in more than one parent (the instancing being talked about in those other threads) and one but not all of those parents are saved after a value has been changed in the subpatch, then each parent gets different values. This is the kind of subtle bug that will consume massive hours of debugging.

And here’s where the problem with this behavior becomes painfully obvious: in the subpatch, create another IOBox hooked to the output IOBox. Now, when you change the new IOBox, everything works as you would expect. The value in the subpatch always appears in all parent patches without them needing to be saved.

That these two cases behave differently (see attached) is VERY counter-intuitive, and I would take issue with the logic in those other threads that the current behavior is what I “want” - what I want is for a value I set in a sub-patch, to be the value that patch outputs all the time forever everywhere, period. As a user I could care less about the internal logic of the implementation.

IOBug2.zip (2.0 KB)

if i understand you right, i’d say its correct and it is just the way it is defined in vvvv. if you want to have static values in a patch that is also an output you need to connect an IOBox without a name that actually holds the values.

if you have only one IOBox that has a name it will be overwritten of whatever is saved in the parent patch because it is also an input in that case. that is why the parent patch asks you to save the values… in this case you are only storing a ‘default’ value in the IOBox. if it wasn’t like that many other cases would not behave as expected. so the IOBox is has quite a lot of roles here and as user you need to understand all of them…

this is way better handled in VL, there storing a value in an IOBox and in/outputs are separated to reduce these kind of complicated behaviors.

But the parent patch DOES NOT ask to be saved, and retains the old value that it is NOT SHOWING at the time. A clear bug.

And I’m sorry, an “output” pin suddenly acting like an input pin (with it’s input coming from the “input” of another node!) makes no sense whatsoever.

Please give me one use-case where this is desirable and/or expected.

Take the following pseudocode:

File 1:

int func1()
{
    return(1);
}

File 2:

func2()
{
    a = func1();
    print a;
}

What are you going to think when you change file 1 to return 42, recompile, run, and still get “1” printed out unless you recompiled file 2 as well? Now is that a “feature” or a “bug”? If C# worked this way there would be mass uprisings.

Now I understand it likely “works” this way as a side-effect of some internal architecture, my point being that it is still counter-intuitive and bad behavior. It even breaks the whole data-flow paradigm of data always going from outputs to inputs.

Here’s perhaps a better example of the problem.

In the attached, the IOBox in patch 3 that is feeding a value into the output IOBox is given a label so it is now an input pin. Change one if its values, and exit, and you are prompted to save only patch 3.

Reload patch 1, and the correct changed values are visible in patch 1. Unlike the case of patch 2, the state of the “input” of patch 3 was NOT overridden by the parent patch.

So in patch 2, it appears as if the IOBox is being treated as an input pin with a saved value of the parent patch propagating into it, but that is not happening with patch 3. So the INPUT value of an IOBox that appears as both an input and output pin is propagated from the parent, but a pure input IOBox it is not unless it is explicitly set in the parent. Again, not expected behavior.

IOBug3.zip (2.0 KB)

ah, got it… it was asking to save when i tested your patches. if it does not, that’s a bug of course.

Yeah, probably why this has not bitten more people is that normally if you opened that subpatch, changed a value, then closed it, you would have been prompted to save the parent and all would have worked as expected.

But not anymore, as just opening/closing subpatches now I believe with 35+ does not cause a save prompt and out pops the gremlin!

OK, so how about this:

I think the real bug is that in the case of an IOBox being both an input and output pin, the parent is saving the value when it has NOT been explicitly set in the parent. Make that case work like an IOBox that is only an input pin: the parent does not store its value UNLESS it has been explicitly set in the parent - which would of course prompt for a save of the parent.

Then when that value is changed in the subpatch, the expected behavior will happen where all patches using it get the current value of the subpatch UNLESS they have explicitly set the input pin of that subpatch otherwise. That is completely consistent and parsimonious.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.