Indy - ReadLnSplit Causes NotConnected Exception when closing - sockets

I use TIdTCPServer and the following code to read client input :
repeat
cl3:=cl3+AContext.Connection.IOHandler.ReadLnSplit(WasSplit,#0,-1,-1,TEncoding.UTF8);
until not WasSplit;
However if client is connected to the server and I close the server it raises an exception class (EIdNotConnected) whith message 'Not connected'.
If I use ReadLn instead ReadLnSplit no exception raises.
What causes this exception and how could I prevent it?
I suppose the solution is simple but I am new to sockets and Indy and I cant figure it out.
Thanks in advance.

What is the actual problem? When you close the server, it is supposed to make active reading/writing operations raise an exception. That is normal behavior for Indy. ReadLn() is just as likely to raise an exception as ReadLnSplit() is. Indy relies on exceptions for its internal notifications. Just let the server handle the exception for you, so it can terminate and cleanup the thread that is managing the TIdContext and its connection. The exception is in the context of that thread, the rest of your code (or your users) will not see it.
The only thing ReadLnSplit() does differently than ReadLn() is to force the IOHandler's MaxLineAction property to maSplit during that call, nothing else. The only reason to use ReadLnSplit() is to handle lines that are longer than the IOHandler's MaxLineLength property without changing the MaxLineLength. If you don't like the way ReadLnSplit() behaves, then don't use it. You could just increase the value of the IOHandler's MaxLineLength property and call ReadLn() instead:
AContext.Connection.IOHandler.MaxLineLength := MaxInt;
cl3 := AContext.Connection.IOHandler.ReadLn(#0, IndyUTF8Encoding);
Or you could call the overloaded version of ReadLn() that has an optional AMaxLineLength parameter:
cl3 := AContext.Connection.IOHandler.ReadLn(#0, IdTimeoutDefault, MaxInt, IndyUTF8Encoding);

Related

How to Troubleshoot Dexie bound on IDBKeyRange Error

I'm using Dexie.js version 3.0.3-rc.3 in a Vue JS project and I occasionally run into this exception in Chrome (86):
Failed to execute 'bound' on 'IDBKeyRange': The parameter is not a valid key.↵ DataError: Failed to execute 'bound' on 'IDBKeyRange': The parameter is not a valid key.
Here's a screenshot of the full error:
I'm fairly certain the problem lies with something in my data being undefined, but I'm trying to find a good way to troubleshoot this. I paused the Chrome dev tools on exceptions and inspected the code around this particular part of Dexie, but it doesn't reveal what data was used to make this exception occur.
Does anyone have any suggestions on how to find out what's actually wrong? It feels a bit like a needle in a haystack.
== Update ==
Below is the full call stack:
Try inspecting the call stack. I know it can be long until you reach a frame within your application code, but the failing call should be there!

UndeliverableException thrown within a RxAndroidBle stream

I have a misbehaving BLE device (temp sensor) that keeps throwing a status 8 (GATT_INSUF_AUTHORIZATION or GATT_CONN_TIMEOUT) exception everytime i try to connect to the device. I'm not concerned about this exception as the device is faulty.
However, I keep getting notified that i've not handled the error correctly by rxjava2 when using RxAndroidBle(1.9.1); see here;
This is my code.
rxBleClient
.getBleDevice(macAddress)
.establishConnection(false)
.flatMapSingle { it.readRssi() }
.subscribe({ "test1:Success" }, { "test1:error" })
and the Error
I/RxBle#GattCallback: MAC='E9:CF:8A:D0:01:19' onConnectionStateChange(), status=8, value=0
D/RxBle#ClientOperationQueue: FINISHED ConnectOperation(147547253) in 10257 ms
D/RxBle#ConnectionOperationQueue: Connection operations queue to be terminated (MAC='E9:CF:8A:D0:01:19')
com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from MAC='E9:CF:8A:D0:01:19' with status 8 (GATT_INSUF_AUTHORIZATION or GATT_CONN_TIMEOUT)
at com.polidea.rxandroidble2.internal.connection.RxBleGattCallback$2.onConnectionStateChange(RxBleGattCallback.java:77)
at android.bluetooth.BluetoothGatt$1$4.run(BluetoothGatt.java:249)
at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:725)
at android.bluetooth.BluetoothGatt.-wrap0(Unknown Source:0)
at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:244)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
at android.os.Binder.execTransact(Binder.java:697)
D/BleDeviceManagerNew$observeRssiTest: test1:error
E/plication$setupApp: Terminal Exception From RXJAVA was Not handled correctly
io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from MAC='E9:CF:8A:D0:01:19' with status 8 (GATT_INSUF_AUTHORIZATION or GATT_CONN_TIMEOUT)
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onError(ObservableUnsubscribeOn.java:67)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onError(ObservableSubscribeOn.java:63)
I'm not sure what else I should do - i've implemented a 'catch all' solution but don't like this approach;
RxJavaPlugins.setErrorHandler { e -> Timber.e(e, "Terminal Exception From RXJAVA was Not handled correctly") }
but don't see that as a good solution as expected that i should be-able to handle exception on the steam. Any suggestions of where I went wrong?
Your code is fine. The library has a flaw that does not allow to achieve your desired behaviour. More on the topic is on this library's wiki page.
While it is possible to design an API that would not throw UndeliverableException it would need to have a separate error Observable or Completable for BluetoothAdapter turning off and a separate one for RxBleConnection disconnect. The user would be responsible to mix those into their chain appropriately.
Current API does not allow it.

SocketError handling in Prolog

I'm a bit unfamiliar with the mechanics of error recovery in prolog, so I apologize in advance if the question seems stupid.
I am looking for a way to properly handle SocketError in swi-prolog. So far I have only found the following snippet:
setup_call_catcher_cleanup(tcp_socket(Socket),
tcp_connect(Socket, Host:Port),
exception(_),
tcp_close_socket(Socket)).
Whenever a connection is refused, it raises the appropriate exception and performs the cleanup action, closing the socket.
Problem is, i want to embed this in a predicate test_socket/3 that sets a status code whenever a connection gets refused and I cannot seem to find a way to do so. I tried doing:
test_socket(Host, Port, Status) :-
setup_call_catcher_cleanup(tcp_socket(Socket),
tcp_connect(Socket, Host:Port),
exception(_),
(tcp_close_socket(Socket), Status = 1).
but this doesn't seem to do the trick. Any ideas?
The purpose of the argument Cleanup is to perform some cleanup action, and then to continue, as if this cleanup has not happened. That is, the exception goes further up and Status = 1 is superfluous. The construct is not made to do everything. But probably a catch/3 above all of this, is what you want.
– false

With Tibco Rendezvous, how catch errors that are being printed to the console?

In Tibco, sometimes warnings are printed to the console, e.g.:
2014-06-25 18:13:22 RV: TIB/Rendezvous Error Not Handled by Process:
{ADV_CLASS="WARN" ADV_SOURCE="RVCM"
ADV_NAME="REGISTRATION.NOT_CERTIFIED.cm.test.subject"
subject="cm.test.subject" sender="cm.sender.cmname"}
I am using the .NET wrappers for Tibco. It appears as if these errors are not actually making it into the .NET, and they can't be caught with try/catch so they can be handled appropriately.
Is there any way to handle this error in .NET? Perhaps some method of registering a handler to handle errors such as this? Or alternatively, is there a method to redirect these warnings into a sink other than the console, e.g. a log file?
The solution is to add a "catch all" handler.
The current subject that I was listening to was:
private readonly string _subjectDeliveryConfirm = "_RV.INFO.RVCM.DELIVERY.CONFIRM.>";
To add a catch all, add another listener on:
private readonly string _subjectDeliveryGlobal = ">";
When you add a new listener, remember to use a separate Listener concrete class per listener, or else Tibco will mysteriously stop working after the first message (see the demo code for how to create multiple listeners).
_confirmListener1 = new Listener(Queue.Default, _netTransport, _subjectDeliveryConfirm, null);
_confirmListener1.MessageReceived += new MessageReceivedEventHandler(OnCertifiedMessageConfirmed);
// Subscribe to error messages, in particular error messages related to remote listener processes
// disappearing.
_confirmListener2 = new Listener(Queue.Default, _netTransport, _subjectDeliveryGlobal, null);
_confirmListener2.MessageReceived += new MessageReceivedEventHandler(OnTibcoCatchAll);
There is lots of sample C# code in the \src\ directory for the Tibco install that illustrates the techniques shown above.

MessageReadPropertyFilter getting reset when using MSMQ

Strange one. We have a multi-threaded app which pulls messages off a MSMQ Queue and then subsequently performs actions based on the messages. All of this is done using DTC.
Sometimes, for some reason I can't describe, we get message read errors when pulling Messages off the queue.
The code that is being used in the app:
Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages();
foreach (Message currentMessage in allMessagesOnQueue)
{
if ((currentMessage.Body is IAMessageIDealWith))
{
// do something;
}
}
When the currentMessage.Body is accessed, at times it throws an exception:
System.InvalidOperationException: Property Body was not retrieved when receiving the message. Ensure that the PropertyFilter is set correctly.
Now - this only happens some of the time - and it appears as though the MessageReadPropertyFilter on the queue has the Body property set to false.
As to how it gets like this is a bit of a mystery. The Body property is one of the defaults and we absolutley never explicitly set it to false.
Has anyone else seen this kind of behaivour or has some idea why this value is getting set to be false?
As alluded to earlier, you could explicitly set the boolean values on the System.Messaging.MessagePropertyFilter object that is accessible on your messageQueue object via the MessageReadPropertyFilter property.
If you want all data to be extracted from a message when received or peaked, use:
this.messageQueue.MessageReadPropertyFilter.SetAll(); // add this line
Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages();
// ...
That may hurt performance of reading many messages, so if you want just a few additional properties, create a new MessagePropertyFilter with custom flags:
// Specify to retrieve selected properties.
MessagePropertyFilter filter= new MessagePropertyFilter();
filter.ClearAll();
filter.Body = true;
filter.Priority = true;
this.messageQueue.MessageReadPropertyFilter = filter;
Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages();
// ...
You can also set it back to default using:
this.messageQueue.MessageReadPropertyFilter.SetDefaults();
More info here: http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.messagereadpropertyfilter.aspx
I have seen it as well, and have tried initializing it with the properties I'm accessing explicitly set, and not setting them anywhere else. I periodically get the same error you are getting, my app is multi-threaded as well, what I ended up doing is trapping that error and reconnecting to MSMQ when I get it.
Sometimes, for some reason I can't describe, we get message read errors when pulling Messages off the queue.
Are you using the same MessageQueue instance from more than one thread, without locking? In that case, you will encounter spurious changes in MessageReadPropertyFilter - at least I did, when I tried.
Why? Because
Only the GetAllMessages method is thread safe.
What can you do? Either
wrap a lock (_messageQueue) around all access to your messageQueue OR
create multiple MessageQueue instances, one per thread