server and astreams problem

mc73

Well-Known Member
Licensed User
Longtime User
Using a server and aStreams, here's something I've noticed: Occasionally server crashes, most probably due to a coding error of mine which I didn't catch, or perhaps due to a wifi failure of the server for a second or two. At least so I believe.
Still, in the client's module, I am using a Astreams_error sub where I've placed a msgbox just to know the cause of the comm problem. What is happening is that server crashes (thus the service module stops) and client remains showing a progressdialog, without astreams to return an error. Is this related to the nature of the progressdialog (i.e. not leaving the msgbox to appear) or I should suspect the astreams behavior?
 

mc73

Well-Known Member
Licensed User
Longtime User
The service module will not stop when the connection breaks.

Does Astreams_error sub execute when the server crashes? Why don't you hide the progress dialog when it happens?
The service module stops because of an error in my coding, this I am sure of. The progress dialog is on the client's side. I was hoping that the msgbox will ignore its existence. If that's not the case, sure, I will hide it immediately.
My problem, Erel, is mainly due to the negativity of my clients to perform the updates I offer, as funny as it may seems. At the same time, they're just a thousand miles away from me, to go and upload the new versions. In my configuration, I NEVER saw this type of error so far and this is the ugly part in trying to debug.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Are you asking what happens when both a ProgressDialog and a Msgbox are displayed at the same time?

You can run this simple test:
B4X:
   ProgressDialogShow2("asd", False)
   Msgbox("test", "")

And see that the msgbox will appear over the progress dialog, which remains visible after the msgbox is dismisses.
Means that the astreams_error is not triggered. Thus, astreams are still open waiting for something from the server's side, which is closed after the service got destroyed? Perhaps, I am missing something here. Wasn't the scope of astreams_error to be triggered in such cases?
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
I'm sorry but I'm still not sure that I understand your questions. Astreams_error will not be raised when a msgbox is displayed. Only after the msgbox is dismissed.

Service modules do not get destroyed unless you call StopService.

I don't use a stopService. t has to be a bug in my code in the service module which leads to service to get destroyed.

The msgbox is inside the astreams_error subroutine. Thus, it should be shown.

B4X:
'client's side
Sub AStreams_Error
Msgbox(LastException.Message,"ok")
End Sub
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
I don't use a stopService. t has to be a bug in my code in the service module which leads to service to get destroyed.

The msgbox is inside the astreams_error subroutine. Thus, it should be shown.

B4X:
'client's side
Sub AStreams_Error
Msgbox(LastException.Message,"ok")
End Sub

Hm, now that I see it again, there is always a chance that the end-user sees the msgbox, clicks 'ok' and not reporting to me the error message. Thus, I cannot be sure of whether the astreams is really triggered or not. I'm sorry, Erel, I guess I have to reconstruct my astreams_error subs, hide the progressdialog, log the error message to a file (if it is there) and probably restart the app. It's just too bad for me, I cannot replicate the bug involved. Again, sorry for wasting your time with this, I'll get back with my report, if I notice that it was not something to do with astreams_error functionality.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Back again, after some changes in my code, with some try-catch, some other filters, in reality, almost everything I could do to prevent the server from crashing. And then, a crash again, even if I'm pretty sure I trapped all possible errors in the 'problematic' sub routine. Anyway, here's the reason of this post: Is it possible that while the server-client connection is established, and server loses its connection with the router - this is what you get when you don't wish to pay too much for a tablet :) - that somehow it can result in my service module crash? Then, over the client's side. I know almost nothing about the net.lib, so, is it possible that when server loses connection, client never receives nor a response, not there is a protective time, in order to protect the app? I know I can use a timer for this, just asking if I miss something in the net.lib's events. Thank you.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
AStreams_Terminated should be raised when the connection is broken. However it is possible that the native driver still "thinks" that the connection is alive.

I recommend you to send a periodically "ping" message from the client which the server should respond to. If there is no response after x pings then you should break the connection.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
AStreams_Terminated should be raised when the connection is broken. However it is possible that the native driver still "thinks" that the connection is alive.

I recommend you to send a periodically "ping" message from the client which the server should respond to. If there is no response after x pings then you should break the connection.

Ah, thank you Erel. I didn't know about astreams_terminated, I guess I will try both this event and a timer for this problematic behavior.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
It's been a 'long' time since I've started this thread, and due to the fact that this problem is a bit rare, I somehow left it behind.
Tonight, though, while debugging other things, the problem arose again, and here's what I found:

It seems like astreams get terminated before my 'closeSocket' command. I can understand a but about some latencies that may cause this, yet, it's a bit weird.
First, here's a 'working' log, no errors:
B4X:
'working
'--------------------------------
command=READDBCHANGES
from socket=0
mydata=dbChanges    1    1    1
socket=0
command=CLOSESOCKET
from socket=0
command=READSHIFTS


from socket=0
string1=1


mydata=shiftExists    3
socket=0
command=CLOSESOCKET
from socket=0
astreams0 terminated
astreams0 terminated
command=READTABLES


from socket=0


string1=1000
workspace=1000
mydata=10000    0    0    0    0    


socket=0
command=CLOSESOCKET


from socket=0
astreams0 terminated


command=READTABLES


from socket=0
string1=1001
workspace=1001


mydata=10004    103.5    0    1    0    10005    104.5    99.5    1    0    10006    147    0    1    0    10003    19.5    0    1    0    10010    0    0    0    0    10002    76    0    1    0    10008    40.5    0    1    0    10011    0    0    0    0    10001    0    0    0    0    10007    0    0    0    0    10009    0    0    0    0    10012    0    0    0    0    10013    0    0    0    0    10025    0    0    0    0    10014    0    0    0    0    10024    0    0    0    0    10015    0    0    0    0    10023    0    0    0    0    10026    0    0    0    0    10022    0    0    0    0    10016    0    0    0    0    10017    0    0    0    0    10020    0    0    0    0    10021    0    0    0    0    10019    0    0    0    0    10018    0    0    0    0    


socket=0


command=CLOSESOCKET


from socket=0
astreams0 terminated



'---------------------------------

And here's a log with error:
B4X:
'error
command=READDBCHANGES
from socket=0
mydata=dbChanges    1    1    1
socket=0
command=CLOSESOCKET
from socket=0
command=READSHIFTS
from socket=0
string1=1
mydata=shiftExists    3
socket=0
astreams0 terminated
command=CLOSESOCKET
from socket=0
command=READTABLES
from socket=0
string1=1001
workspace=1001
mydata=10004    103.5    0    1    0    10005    104.5    99.5    1    0    10006    147    0    1    0    10003    19.5    0    1    0    10010    0    0    0    0    10002    76    0    1    0    10008    40.5    0    1    0    10011    0    0    0    0    10001    0    0    0    0    10007    0    0    0    0    10009    0    0    0    0    10012    0    0    0    0    10013    0    0    0    0    10025    0    0    0    0    10014    0    0    0    0    10024    0    0    0    0    10015    0    0    0    0    10023    0    0    0    0    10026    0    0    0    0    10022    0    0    0    0    10016    0    0    0    0    10017    0    0    0    0    10020    0    0    0    0    10021    0    0    0    0    10019    0    0    0    0    10018    0    0    0    0    
socket=0
serverlistener_senddatatoclient (java line: 717)

java.lang.NullPointerException
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams.Write2(AsyncStreams.java:93)
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams.Write(AsyncStreams.java:85)
    at wos.androidserver.serverlistener._senddatatoclient(serverlistener.java:717)
    at wos.androidserver.serverlistener._serverreadtables(serverlistener.java:1873)
    at wos.androidserver.serverlistener._servercueproccess(serverlistener.java:1353)
    at wos.androidserver.serverlistener._astreams0_newdata(serverlistener.java:139)

By comparison, I see that in the second case (the one that errors) I have a aStreams_terminated just before I send a 'closeSocket'. Then, since, I want to send data again to this socket, I guess that this is the reason I receive the nullPointerException.
But, it's just the same code, I don't get why this occasional thing is happening. Any ideas?

By the way, Erel, I would like to know if the aStreams java error (lines 85,93 of aSyncStreams) I receive is due to the string sent, or to the socket. If it's the latter, I can assume that the hypothesis that my socket is closed while I try to feed it with data, is valid.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Sure I can't write after 'termination', exactly! This is what bothers me, the termination while still in writing. I don't close socket in the mean time, nor there exists another error.
BUT I do have a closeSocket&Stream after the 'closesocket', in the activity.finish. Somehow I think that the operation is very fast and the server is not receiving the closeSocket before the termination. I have an idea, and I need your advice, of course: How about not even sending a closeSocket, terminating the stream&socket, thus moving to the server's astreams_terminated? At the same time, just to be sure that the connection is really closed (I remember your quote about the streams_terminated may not be triggered sometimes due to the OS), I'll setup a timer of some seconds. When server receives nothing in its aStreams_newData, I will simply close its sockets. Is there something here, I should be cautious of?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Some advices that I hope will help you:
- Don't manage the streams and sockets from an Activity. Do everything from a service.
- See B4A-Bridge source code.
- Implement a heart-beat (or ping) mechanism. Send one byte from the server to the client each second. The client should respond with one byte. This way (together with Terminated and Error events) if after 10 seconds no ping arrived you should close the connection.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Some advices that I hope will help you:
- Don't manage the streams and sockets from an Activity. Do everything from a service.
- See B4A-Bridge source code.
- Implement a heart-beat (or ping) mechanism. Send one byte from the server to the client each second. The client should respond with one byte. This way (together with Terminated and Error events) if after 10 seconds no ping arrived you should close the connection.

Thank you very much for your advice, quite closed to my intentions right now. But here's the story about activities: Most of the time (to not say always), I just a need 2-3 bytes from the server (e.g. 'tell me this client's password' or 'send me the quantity of this item' and so on). So, I don't really want to keep connection open for more than 0.2-1sec max, each time an activity is loaded. I am kinda afraid of the battery-drain effect, in case I keep connections open, and this was the reason for closing connections. Till now, I manage to keep devices running with WIFI for as long as 16 hours, and I presume this has to do with this small activity of them.
Anyway, it's not a problem to try to replace all existing subs with a more generic one in a module at the client's side (in the server's side, i already use a service at foreground). Thank you very much, once more!
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
So far, so good. I replaced my initial 'closeSocket' commands, with simply closing the streams and the sockets. Streams_terminated works excellent, tested these 3-4 hours now. I decided to avoid timers for the moment and get back to put them in the game, if I find out inconsistencies in streams_terminated sub. I have some very inconsistent devices (when it comes to their WIFI stability), thus sooner or later, I will know if the OS fails to recognize a terminated stream. Surely, I'll post here my findings, if any.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
Ok, back. Seems like termination subs do not work consistently, thus, I turned to Erel's advice and placed all network connections to a service module. It works pretty well, furthermore it made me understand a key problem of my coding: I was closing sockets, in order to free them when not necessary any more. But, I didn't realize that occasionally it takes time to finish a process (sqlite non-quering) and I was mistakenly closing the sockets before the process terminations. This was leading to broken sockets. Services helped me not only reveal this fundamental bug of my code, but also get rid of it. Thank you, Erel.
 
Upvote 0
Top