|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
A procedural error can affect memory over time. I noticed that when using /SOCKREAD &BINVAR and if during the Sockread Event I do: if ($sockbr == 0) return This BinVar is not removed from memory. The mIRC examples basically show /SOCKREAD %VAR For this reason the code should be: if ($sockbr == 0) { bunset &BINVAR | return } ON *:SOCKREAD:mySocket:{ if ($sockerr > 0) { return } sockread &MyVar ;ERROR MEMORY if (!$sockbr) return ;FREE MEMORY if (!$sockbr) { bunset &MyVar | return } ;;; Your Code } If you have a recurring Socket command, you will notice your memory gradually rising without stopping. https://en.wikichip.org/wiki/mirc/on_events/on_sockreadhttps://en.wikichip.org/wiki/mirc/commands/sockreadThanks!
|
|
|
|
Joined: Jan 2004
Posts: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
If &MyVar is not being unset, then you should be able to put the debugging message echo -s event $event $bvar(&MyVar) $bvar(&MyVar,0) at the top of your ON SOCKREAD event and find that it exists with a non-zero size, and I don't see that when I add that check to one of my scripts. While there might be a memory leak of some kind, your example doesn't demonstrate it. Also, if you are finding sockread causing mirc memory to increase gradually due to a &binvar not being unset, does the increase stop happening if you instead have it read to a %variable ?
|
|
|
|
Joined: Dec 2002
Posts: 5,474
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,474 |
Thanks for your bug report. I have not been able to reproduce this issue here.
In my tests, the &binvar is automatically freed when the on sockread event ends.
You can test for this by, eg. calling //echo $bvar(&binvar,0) after the on sockread event exits.
Can you provide a script that reproduces your issue? Your test script should use /socklisten, /sockopen, /sockwrite, and the socket events, so that I can run it here to reproduce your issue.
|
|
|
|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
You need to let him read for a long time to notice. Here I left it for a day in a loop opening and closing the socket.
The problem is the return before finishing the Sockread Event. It will prevent the Event from finishing and &BinVar's memory will not be released.
Put a Return at some point and you will see that the memory will not be freed.
I showed this case, because that's how the example explains the return in case of $sockbr, but any return will cause the failure of not freeing the memory.
|
|
|
|
Joined: Jan 2004
Posts: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
Heya, reminder you had 2 replies asking you to give an example that demonstrates this memory leak bug. You're basically asking to have the other person create a script, then run it for a day, with the promise that they'll see an unstated memory increase.
|
|
|
|
Joined: Dec 2002
Posts: 5,474
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,474 |
Okay, I ran a test script that sent almost a gigabyte of data, received in the sockread event into a &binvar, and there has been no memory loss so far.
This is the reason why I ask scripters to please provide an example script that reproduces their issue. I can spend all day guessing at what your script looks like, what calls it makes, the order of calls, etc. but that will not help.
Your last post says that "Here I left it for a day in a loop opening and closing the socket." So this might have nothing to do with &binvars. This might be related to repeatedly opening and closing sockets.
Please provide a working test script that reproduces the issue for you.
|
|
|
|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
My Example:
ON *:SOCKREAD:mySocket:{ if ($sockerr > 0) { return } sockread $+(&,$sockname) ;ERROR MEMORY if ($sockbr == 0) return ;FREE MEMORY ;;;if (!$sockbr == 0) { bunset $+(&,$sockname) | return } ;;; Your Code }
It is necessary for $sockbr to return 0 to cause the problem of not freeing memory.
Here this type of example gives trouble. If $sockbr is zero and the return is triggered.
|
|
|
|
Joined: Jan 2004
Posts: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
this is not an example. You can put this code into a clean copy of mirc and i promise this does nothing for 100 years. You're being asked for code to show the bug, and this isn't that.
|
|
|
|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
I guarantee you that this code does not free up memory. I use it in my code here and you can put me read from socket to html page and you will see this error occur. I guarantee you with absolute certainty. After I freed the memory before the return the problem stopped. After a day running the memory doubled in size. If I put this code there, just a socket that reads some simple html page is enough.
|
|
|
|
Joined: Jan 2004
Posts: 2,127
Hoopy frood
|
Hoopy frood
Joined: Jan 2004
Posts: 2,127 |
Sorry, I'm checking out. I dunno why you don't want to just provide some example code that would demo this bug in a clean mirc.
|
|
|
|
Joined: Jul 2006
Posts: 4,180
Hoopy frood
|
Hoopy frood
Joined: Jul 2006
Posts: 4,180 |
Hello,
The script you provided has a theorical misconception, so if it works the way you're implying it does, then the socket design/event is far more broken than just a leak.
In theory, you're reading into a binvar without specifying a number of bytes so a default of 4096 bytes is read into the buffer. Let's say data arrives on the socket, any data, on sockread triggers, 4096 bytes (or less if less) are read, $sockbr isn't 0. 1) if you have read the full buffer and no more data is available, per the note in the help file under /help /sockread, on sockread won't retrigger in this case, so, certainly not with $sockbr = 0. 2) if you haven't read the full buffer, on sockread retriggers and we're back to reading 4096 or less bytes etc (your on sockread event logic guarantees data is there if the event is triggered)
So it should not be possible for this on sockread event to trigger with $sockbr = 0.
Which version of mIRC are you using, are you using SSL?
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Apr 2010
Posts: 969
Hoopy frood
|
Hoopy frood
Joined: Apr 2010
Posts: 969 |
win10 mIRC v7.72 (Fresh install; no coms, dlls, or unrelated scripts) I cannot reproduce this after testing a veriety of ways. Things I've tried: Singular sockread calls across multiple events: on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [CLIENT] SockRead error
sockread 8192 &bvar
} Multiple sockread calls in the same event on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [CLIENT] SockRead error
sockread 1024 &bvar
sockread 1024 &bvar
sockread 1024 &bvar
sockread 1024 &bvar
} Context dependant sockread calls: on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [CLIENT] SockRead error
sockread 1024 &bvar
while ($sockbr) {
sockread 1024 &bvar
}
} The script used (sub out the SOCKREAD test-client event):
;; To start the test: /test-start
alias test-start {
socklisten test-listener 1010
echo * [Host] Listening for connections
startclient
;; adjust timer to alter run length
timerteststop 1 15 test-stop
}
alias test-stop {
if ($sock(test-listener)) {
sockclose test-listener
}
if ($sock(test-host)) {
sockclose test-host
}
if ($sock(test-client)) {
sockclose test-client
}
if ($timer(teststop)) {
timerteststop off
}
if ($0) {
echo * $1-
}
else {
echo * Test ended
}
halt
}
; Setup Listener
on *:SOCKLISTEN:test-listener:{
if ($sockerr) test-stop [LISTENER] SockListen error
sockaccept test-host
sockwrite -t test-host str(a, 8192)
}
on *:SOCKCLOSE:test-listener: {
if ($sockerr) test-stop [LISTENER] SockClose error
test-stop [LISTENER] Listener closed
}
/*
** Host/server side of connection
** Attempts to keep the send-buffer at 8kb
*/
on *:SOCKWRITE:test-host:{
if ($sockerr) test-stop [HOST] SockWrite error
var %space = $calc(8192 - $sock($sockname).sq)
if (%space > 0) {
sockwrite -t $sockname $str(a, %space)
}
}
on *:SOCKCLOSE:test-host: {
if ($sockerr) test-stop [HOST] SockClose error
test-stop [HOST] Shutdown: Client disconnected from host
}
/*
Client: Connects to host, reads received data into bvar, then returns
*/
alias -l startclient {
sockopen test-client 127.0.0.1 1010
echo * [Client] Connecting to host...
}
on *:SOCKOPEN:test-client: {
if ($sockerr) test-stop [CLIENT] SockOpen error
echo * [Client] Connected to host.
}
on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [Client] SockRead error
sockread 8192 &mybvar
}
on *:SOCKCLOSE:test-client:{
if ($sockerr) test-stop [Client] SockClose error
test-stop [Client] Connection to host closed
}
|
|
|
|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
|
|
|
|
Joined: Nov 2021
Posts: 33
Ameglian cow
|
OP
Ameglian cow
Joined: Nov 2021
Posts: 33 |
Your example:
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 8192 &bvar }
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 1024 &bvar sockread 1024 &bvar sockread 1024 &bvar sockread 1024 &bvar }
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 1024 &bvar while ($sockbr) { sockread 1024 &bvar } }
Where is the return?
THE PROBLEM IS RETURNING AFTER /SOCKREAD, UNDERSTAND?
Modifying your code:
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 8192 &bvar if ($sockbr == 0) return }
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 1024 &bvar if ($sockbr == 0) return sockread 1024 &bvar if ($sockbr == 0) return sockread 1024 &bvar if ($sockbr == 0) return sockread 1024 &bvar if ($sockbr == 0) return }
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 1024 &bvar if ($sockbr == 0) return while ($sockbr) { sockread 1024 &bvar if ($sockbr == 0) return } }
If you want, just put a return later without checking the $sockbr:
on *:SOCKREAD:test-client:{ if ($sockerr) test-stop [CLIENT] SockRead error sockread 8192 &bvar return }
|
|
|
|
Joined: Apr 2010
Posts: 969
Hoopy frood
|
Hoopy frood
Joined: Apr 2010
Posts: 969 |
Still cannot reproduce after testing the following: Singular Read per event on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [Client] SockRead error
sockread 8192 &mybvar
return
} Multi-read per event on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [Client] SockRead error
sockread 4092 &mybvar
sockread 4092 &mybvar
return
} State-specific read per event on *:SOCKREAD:test-client:{
if ($sockerr) test-stop [Client] SockRead error
sockread 1024 &bvar
while ($sockbr) {
sockread 1024 &bvar
}
return
}
|
|
|
|
Joined: Dec 2002
Posts: 5,474
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,474 |
I have added this line, in several places, to the on sockread event in my test script and it has made no difference. I also tried: if ($sockbr == 0) { echo 4 sockbr is zero return } The above message never displays because $sockbr is never set to zero, which means /return can never be called. I also added just /return to the script in different places. &binvars are freed automatically at the end of a script. This is completely independent of what a script does and cannot be prevented. So my guess is that the issue you are seeing is not related to &binvars and is due to something else in your script. I realize that you are trying to help, and it's possible that there is a bug, but if no one here is able to reproduce it, we really need a test script from you that reproduces the issue for you, so we can try to track it down. Thanks for your help everyone.
|
|
|
|
|