Forum

Unreliable output of Executor

Hello there,

Trying to run some python scripts with the Executor node here. It looks like the Output and Error output pins behave in an inconsistent way.

You’ll find a little POC attached. It’s just a silly Python script that writes two strings to the console and finally raises an exception. The vvvv patch simply runs it and queues the Output and Error events.

As you can see, Executor randomly outputs empty strings in place of messages/errors. After a bunch of runs, it eventually outputs something but the behavior is rather random : sometimes the messages are doubled, sometimes you get only the errors, sometimes only the messages.

py_executor

  • On first runs, Executor gives empty strings
  • Then it works but the strings are fired twice
  • Only the last print() statement of the python script seems to make it to the output

Tried the same setup with a Sampler instead of HoldLatest and then again, the results are somehow better since all the strings are printed but the results are not consistent :

py_executor_sampler

Test bench is attached here :

executor_output.zip (3.2 KB)

Any hints there?

Thanks!

1 Like

Hey, I assigned the events inside Executor to Create (and tidied up the Process a little :) . Appears to be working reliably now.

executor_output_b.7z (14.0 KB)

2 Likes

Hey there, thanks for looking into it :)

Ran your test patch here, indeed I get more reliable results here, no more empty output (why does assigning the events to Create fixes that by the way? I mean I get why it makes sense to assign those to Create but why does it produce a different behavior if they’re on Update? Shouldn’t that be “just” less optimized?)

But leaving your patch run for a while shows inconsistent output as well :

I’m a bit puzzled because I don’t see what could go wrong and produce that inconsistent behavior - shouldn’t the process behave the same way all the time?

Anyway, at least now we get something all the time, thanks again!

You might need to recreate whole thing, I was playing around with power shell and I noticed that stuff like process aren’t statically bound to their memory address or more likely shell address might change over time, so when you call for process you have to get instance you are starting it for. it’s might be something similar with executor, basically it in moment it was created the shell instance was one, but after some time shell instance updated but executor don’t have correct address anymore…

I would make some utility and wrap whole executor thing in it to make sure you create new executor for each time you trigger…

I think (but don’t know for sure) when put on Update it “re-subscribes” to the events every frame, so subscription to and firing of the events might “overlap” in a way that the result is not received.

What was the time between the executions? I guess if the period is really short the (python) processes could kind of queue up (maybe one overtaking the other) and their results arriving out of order. Just speculation though.

right, I see!

just used the value you set on the LFO :)

ouch, thanks for the pointer, will see if I can implement such a thing when I get back to it!

thanks for that report. we’ve reworked the Executor and added a little help patch for 2021.4.10

2 Likes

@joreg since the Executor update the pin “Time to Wait for Exit” is gone. Is there a reason why or just a accident? Any chance to get the pin back?

Seems to work here if I add it again to the Process.

we took it away on purpose because it felt problematic. can you please share your usecase?

I’m porting a old beta patch to control stepper motors via TIC USB Stepper Motor Controllers. The commands are send via ticcmd, which i call via the Executor.
For example if the position command is called very often because it is change via the UI, sometimes the process hang and did not exit and flooded the Task-Manager. So it was handy that the process was killed after some time.

And the source VL.Devices.TIC-Stepper.zip (2.0 MB)

A new thread for this topic?

heh, so you want to keep it because it helped to workaround another issue you had. hm…
two suggestions:

  • the preferred way: instead of relying on a commandline tool, why not communicate via serial directly? VL has very premium support for serial communication and this would mean your patch will later also run from other platforms…
  • alternative: if you need to kill a process started via Executor, use the Kill node

This is the standard way they provide the communication via USB.They do not open a serial port via USB. All there examples doing the usb communication via ticcmd (python example). For serial via usb a extra adapter or device in between is needed and is quite extra effort to implement the serial protocol.

Yeah, was thinking about this way, but what is the problem with the “Wait for Exit” method? So i would reimplementing a function, which is there and was working for me. And the method is just used wenn the value of pin is set. So could it be a hidden pin?

the issue is with the observable outputs not making sense in the blocking case. so if we bring it back it would have to be an extra node that has a different pin signature…

but in your case, as it sounds like a very special “workaround” usecase, i’d suggest you to simply make a copy of the node in your library that works as you need it.

1 Like

Did not get that the “WaitForExit” was blocking. So I go for the kill option. Thanks for pointing.

I just tested the initial example of @sebescudie with the new 2021.10, but still getting the same results as he described with the new executor…

it’s complicated:

  • the initial patch is flawed as it uses HoldLatest where it should use a Sampler to really get all results
  • there is still a bug in string IOBoxes to not handle the display of null entries correctly

so to see that it works correctly you’ll have to print to console instead of using ioboxes for display.

I’m getting proper results on 2021.4.10 stable with this setup :

image

Snippet

Copy and paste this :

<?xml version="1.0" encoding="utf-16"?>
<Patch xmlns:p="property" Id="VJvl1Sq51p1NaJPBgZR97J" MergeId="475522">
  <Canvas Id="E6OLBrQquWwQJGbfLpCH0y" MergeId="475523" CanvasType="Group">
    <Node Bounds="292,351,85,19" Id="E2bOvn0Iwj1L2BSqirqBep">
      <p:NodeReference LastCategoryFullName="System" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="ProcessAppFlag" Name="Executor" />
      </p:NodeReference>
      <Pin Id="AReBqZTM8CqOquANFoLHGh" Name="File Name" Kind="InputPin" />
      <Pin Id="Jq4XbJ7A2KsPzbjqHeGHKC" Name="Arguments" Kind="InputPin" />
      <Pin Id="Gt8g71iFX9JNUjqSrhsshU" Name="Working Directory" Kind="InputPin" />
      <Pin Id="AW92iz91cvrMu4xnLeLtAJ" Name="Execute" Kind="InputPin" />
      <Pin Id="A7giR6gL1cINMnxdP95Ejr" Name="Output" Kind="OutputPin" />
      <Pin Id="ClyUGLPUXvUQDyAt3J41En" Name="Error" Kind="OutputPin" />
      <Pin Id="OgjSXA54B8kMYpCghoGwN8" Name="Exited" Kind="OutputPin" />
      <Pin Id="AArPBVPxKbKPbiPYlOTiIC" Name="Id" Kind="OutputPin" />
      <Pin Id="T0I3OfKMY3xQMovq6rl1iV" Name="IsRunning" Kind="OutputPin" />
      <Pin Id="JPpAADZtxLKLh3LulIX2bd" Name="Exit Code" Kind="OutputPin" />
    </Node>
    <Pad Id="H1bNaD0Z23DP8K24y7moAX" Comment="File Name" Bounds="294,230,201,15" ShowValueBox="true" isIOBox="true" Value="python">
      <p:TypeAnnotation LastCategoryFullName="Primitive" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="TypeFlag" Name="String" />
      </p:TypeAnnotation>
    </Pad>
    <Pad Id="HWdCQGzIcXPPKag82kOFTs" Comment="Arguments" Bounds="314,259,78,15" ShowValueBox="true" isIOBox="true" Value="dummy.py">
      <p:TypeAnnotation LastCategoryFullName="Primitive" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="TypeFlag" Name="String" />
      </p:TypeAnnotation>
    </Pad>
    <Node Bounds="348,284,87,19" Id="ELafGI48hEkMf5Gs6cV7Po">
      <p:NodeReference LastCategoryFullName="System.Application" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="ProcessAppFlag" Name="ApplicationPath" />
      </p:NodeReference>
      <Pin Id="JlBv17vN5SbLYgTWWyX0u8" Name="Output" Kind="OutputPin" />
    </Node>
    <Pad Id="HSPtVkx0UZ2PcdTLKYAfSt" Comment="Execute" Bounds="398,326,35,15" ShowValueBox="true" isIOBox="true" Value="False">
      <p:TypeAnnotation>
        <Choice Kind="ImmutableTypeFlag" Name="Boolean" />
        <FullNameCategoryReference ID="Primitive" />
      </p:TypeAnnotation>
      <p:ValueBoxSettings>
        <p:buttonmode p:Assembly="VL.UI.Forms" p:Type="VL.HDE.PatchEditor.Editors.ButtonModeEnum">Bang</p:buttonmode>
      </p:ValueBoxSettings>
    </Pad>
    <Node Bounds="390,432,53,19" Id="MRWCXCyT4ejLhsU5n9wbjY">
      <p:NodeReference LastCategoryFullName="Reactive" LastSymbolSource="VL.Reactive.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="ProcessAppFlag" Name="Sampler" />
      </p:NodeReference>
      <Pin Id="VWf5uYD1Nz5MyID7Ip7kLw" Name="Async Notifications" Kind="InputPin" />
      <Pin Id="MYSAThkaSMANE59ymPNopO" Name="Notifications" Kind="OutputPin" />
      <Pin Id="RfU9onmVA5cPuUMJtdWuJI" Name="On Data" Kind="OutputPin" />
    </Node>
    <Node Bounds="344,512,34,19" Id="TgUjv1T6II4LF5XH6vmJ68">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="Join" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="PcayyeLG5yELntkjt8w5XD" Name="Separator" Kind="InputPin" />
      <Pin Id="F4b3vPztMxSNRBnxQDKJoE" Name="Values" Kind="InputPin" />
      <Pin Id="O1B4Nb3KUD9MOoJbcADLFe" Name="Output" Kind="StateOutputPin" />
    </Node>
    <Node Bounds="299,457,54,19" Id="QR6fkDSdWz9Nm0sP5FD9aa">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="NewLine" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="CNZk2skTKB2ORL7GPKTSV5" Name="New Line" Kind="OutputPin" />
    </Node>
    <Node Bounds="376,607,58,26" Id="REAFZVByXNpQKm59QN7edz">
      <p:NodeReference LastCategoryFullName="System.Console" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="WriteLine" />
      </p:NodeReference>
      <Pin Id="Ri8kEkWmY6qPKbe2DDx9eA" Name="Value" Kind="InputPin" />
      <Pin Id="SQaMumNjSSuMOxRD24veC0" Name="Apply" Kind="InputPin" DefaultValue="True" />
    </Node>
    <Node Bounds="317,558,85,19" Id="PFsVUGtCCkLPtFgnfVCA5g">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="Format" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="JmGyWybYjvwNRMtnu8qyPT" Name="Format" Kind="InputPin" DefaultValue="#### ERROR&#xD;&#xA;{0}" />
      <Pin Id="Rdtl0egSoOZP27QXFPIA2O" Name="Input" Kind="StateInputPin" />
      <Pin Id="Ij2fAe1ii4uQMRVJG4jiA6" Name="Input 2" Kind="InputPin" />
      <Pin Id="Uo23xhdmyJTLEgc0m4Z4IP" Name="Input 3" Kind="InputPin" />
      <Pin Id="SGHV60pMw1ILqnXXJhgKGb" Name="Input 4" Kind="InputPin" />
      <Pin Id="TV3E7uU3ed9OrbguWDpHqC" Name="Output" Kind="StateOutputPin" />
    </Node>
    <Node Bounds="205,437,53,19" Id="UTcXUPqTEXAMzB8knSw4rj">
      <p:NodeReference LastCategoryFullName="Reactive" LastSymbolSource="VL.Reactive.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="ProcessAppFlag" Name="Sampler" />
      </p:NodeReference>
      <Pin Id="Edq9frJrNQYOEXADCPzyrO" Name="Async Notifications" Kind="InputPin" />
      <Pin Id="ANepPUTZBEmM7LpTfMMyF9" Name="Notifications" Kind="OutputPin" />
      <Pin Id="SoVsLeoRFFFPL7nnKaPMQt" Name="On Data" Kind="OutputPin" />
    </Node>
    <Node Bounds="159,517,34,19" Id="JKyJMLBG2ixNwtcZYatD2g">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="Join" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="QIHCZ4XUdLSOrMvaUVmRqO" Name="Separator" Kind="InputPin" />
      <Pin Id="JvV38wfLtrKPzppWUXTmHm" Name="Values" Kind="InputPin" />
      <Pin Id="KH60j0t3pJlN7RTQIzjJRO" Name="Output" Kind="StateOutputPin" />
    </Node>
    <Node Bounds="114,462,54,19" Id="EaVdRsfpaxVOdQTIAUNnPm">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="NewLine" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="Prv1V9bJB4oLzmdhrRV4fV" Name="New Line" Kind="OutputPin" />
    </Node>
    <Node Bounds="191,612,58,26" Id="GwsU7cxxIWEMyYgeG0n1AV">
      <p:NodeReference LastCategoryFullName="System.Console" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="WriteLine" />
      </p:NodeReference>
      <Pin Id="PXhSFEnFIAbN4amxIIrPvj" Name="Value" Kind="InputPin" />
      <Pin Id="C6S78qqVsWTMTdS4L9Fyed" Name="Apply" Kind="InputPin" DefaultValue="True" />
    </Node>
    <Node Bounds="132,563,85,19" Id="N2xYwOaB87zM7B8TnrsVTS">
      <p:NodeReference LastCategoryFullName="Primitive.String" LastSymbolSource="CoreLibBasics.vl">
        <Choice Kind="NodeFlag" Name="Node" Fixed="true" />
        <Choice Kind="OperationCallFlag" Name="Format" />
        <CategoryReference Kind="StringType" Name="String" NeedsToBeDirectParent="true" />
      </p:NodeReference>
      <Pin Id="TY6MoVTyUIPMBxWwdq9PUu" Name="Format" Kind="InputPin" DefaultValue="#### MESSAGE&#xD;&#xA;{0}" />
      <Pin Id="QGEBZVxvsgiPDXEgr3vOyq" Name="Input" Kind="StateInputPin" />
      <Pin Id="AwXc1hD6Vi5NqnmmMdsv6H" Name="Input 2" Kind="InputPin" />
      <Pin Id="KRKkCnt9w9zQMCVgkKdu4J" Name="Input 3" Kind="InputPin" />
      <Pin Id="KNy0vutzsFpMNXgX5RXTdb" Name="Input 4" Kind="InputPin" />
      <Pin Id="O2BgBkOLQ0nPNjMIkhikRK" Name="Output" Kind="StateOutputPin" />
    </Node>
  </Canvas>
  <Link Id="KYpjZwPaOh0MMw52aMbaIB" Ids="H1bNaD0Z23DP8K24y7moAX,AReBqZTM8CqOquANFoLHGh" />
  <Link Id="Jcc01eQqG5sLO8bt3Y2Itr" Ids="HWdCQGzIcXPPKag82kOFTs,Jq4XbJ7A2KsPzbjqHeGHKC" />
  <Link Id="MEbo5HUQnCXOMLUErTBUmz" Ids="JlBv17vN5SbLYgTWWyX0u8,Gt8g71iFX9JNUjqSrhsshU" />
  <Link Id="GLgnJhlNJv7NqVn1EqdE4g" Ids="HSPtVkx0UZ2PcdTLKYAfSt,AW92iz91cvrMu4xnLeLtAJ" />
  <Link Id="JaKIOIC8MuzO6YL3scEODP" Ids="ClyUGLPUXvUQDyAt3J41En,VWf5uYD1Nz5MyID7Ip7kLw" />
  <Link Id="JVdiS9t7cMYPDBPeM9ifkp" Ids="MYSAThkaSMANE59ymPNopO,F4b3vPztMxSNRBnxQDKJoE" />
  <Link Id="E2XJbwhC2yaLKcpNWne6Fe" Ids="CNZk2skTKB2ORL7GPKTSV5,PcayyeLG5yELntkjt8w5XD" />
  <Link Id="Q6B3zsF7HlDMYWLkfcHcXK" Ids="RfU9onmVA5cPuUMJtdWuJI,SQaMumNjSSuMOxRD24veC0" />
  <Link Id="F8BDr9ijNF3PIzFjM92FqG" Ids="O1B4Nb3KUD9MOoJbcADLFe,Rdtl0egSoOZP27QXFPIA2O" />
  <Link Id="GA6N21FEc7EMBbYkdvr949" Ids="TV3E7uU3ed9OrbguWDpHqC,Ri8kEkWmY6qPKbe2DDx9eA" />
  <Link Id="Uy4Wm2J0o9sMEPx0zuxtPE" Ids="ANepPUTZBEmM7LpTfMMyF9,JvV38wfLtrKPzppWUXTmHm" />
  <Link Id="EuABIMKIE9XNkOjWpJqw6O" Ids="Prv1V9bJB4oLzmdhrRV4fV,QIHCZ4XUdLSOrMvaUVmRqO" />
  <Link Id="UaTXBX1Er8CQWa2cQYfOr0" Ids="SoVsLeoRFFFPL7nnKaPMQt,C6S78qqVsWTMTdS4L9Fyed" />
  <Link Id="PlyugBrUWUkLe22Mauinz0" Ids="KH60j0t3pJlN7RTQIzjJRO,QGEBZVxvsgiPDXEgr3vOyq" />
  <Link Id="RVpQoSNJa4COScNiG4oSlk" Ids="O2BgBkOLQ0nPNjMIkhikRK,PXhSFEnFIAbN4amxIIrPvj" />
  <Link Id="IqVQjPMbnkxLrFdEOq0pIv" Ids="A7giR6gL1cINMnxdP95Ejr,Edq9frJrNQYOEXADCPzyrO" />
</Patch>
2 Likes

You can also do the write line in the event, with a foreach reactive…