system.tag.writeBlocking() not handled by try/except block

Hi,

I am trying to catch timeouts of system.tag.writeBlocking() function (Ignition version 8.1.32).
For testing purposes, I have configured a tag change script on a tag that switches to 0 every 4 seconds.

def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
	if currentValue.value == 0: 
		logger = system.util.getLogger("handling_timeout_test")
		logger.warn("writing on opc tag")
		values = [system.date.getSecond(system.date.now())]
		try:
			system.tag.writeBlocking(["[default]TAG_WITH_LATENCY"], values, 300)
		except:
			logger.error("failed writing on opc tag")

The tag TAG_WITH_LATENCY points to an OPC server that has a 1 second latency for every write.

However, the timeout error is not catched properly, and I get "Error during blocking write of tags through scripting." in the gateway logs :


I don't get the error log that I put in the except clause either.

If I try to execute this same script from the script console on my designer though, the timeout is caught properly.

Would anyone have any idea about the root cause of such behavior ? Thanks in advance for your help !

The 300 you specify there seems to be 300ms, so if your write doesn't happen within that time, you'll get a timeout error. I'm not sure that this is the issue, but that's what I wanted to bring up after a quick glance at the docs.

Yes, you are right. However, when the function times out, I would expect the error to be caught by my try/except block. Turns out it's not the case..

For complicated reasons, Jython exceptions are distinct from Java exceptions, and so you need to catch both, separately:

4 Likes

That's interesting --
this is still the case even with a bare except?
I would expect that to grab anything, not type specific

Now-a-days, I recommend using java.lang.Throwable instead of java.lang.Exception, so that you don't have any name collision with python's Exception class, and to also catch Java Error instances.

2 Likes

Yes, it's still the case.

Thank you for all your answers and for the insights, I did not know that except: clause alone did not catch Java errors.
Nevertheless, I have modified my script to use java.lang.Throwable and it still has not solved the issue...
Below is the updated script :

def valueChanged(tag, tagPath, previousValue, currentValue, initialChange, missedEvents):
    import java.lang.Throwable
	if currentValue.value == 0: 
		logger = system.util.getLogger("handling_timeout_test")
		logger.warn("writing on opc tag")
		values = [system.date.getSecond(system.date.now())]
		try:
			system.tag.writeBlocking(["[default]TAG_WITH_LATENCY"], values, 300)
		except java.lang.Throwable, e:
			logger.error("java Exception : failed writing on opc tag")
		except:
			logger.error("failed writing on opc tag")

The Exception is being caught and logged, it's not re-thrown. There will be a QualityCode.Error_Exception at the corresponding index for the results of the call.

edit: actually all of the results will be Error_Exception in this case.

It seems the implementation is inconsistent between Client and Gateway scopes. Client scope wraps and re-throws via Py.JavaError(e).

2 Likes

Why are you not collecting and examining the quality codes returned from writeBlocking() ? That's how most problems are reported.

1 Like

Ok thank you very much for this explanation ! If I understood well, the code does not go into the except clause at all so I am not seeing those logs.
Is there a way I can remove this timeout log that appears on the gateway still ? I find it hard to troubleshoot, I prefer to implement custom logs describing which tags timed out following the method @pturmel mentioned.

Unfortunately the only thing you could do is turn that logger (Scripting[system_util_tag]) off entirely, which means you wouldn't see any log messages from it at all, perhaps hiding other issues.

1 Like

Sorry one last question because I read too fast earlier on:

edit: actually all of the results will be Error_Exception in this case.

This means that even if the write to a single tag times out and the other writes are successful, QualityCode of Error_Expression will be returned for every write ?
Is there a way to know which write has timed out precisely ?

No, because the timeout isn't per tag, it's for the whole call. If it times out, the entire batch that was submitted got no results. We have no idea what writes were successful at that point.

Ah, that's an issue... would you advise another way of writing to a batch of tags that would handle this kind of problem ?

There isn't one, you can't have both batch performance and individual tag timeout/result.

You can loop and write one tag at a time and pay the performance penalty if you absolutely need per tag timeout/result.

1 Like