mIRC Home    About    Download    Register    News    Help

Topic Options
#264121 - 30/10/18 05:25 AM /saveini writing temp global vars
maroon Offline
Hoopy frood

Registered: 12/01/04
Posts: 969
Not sure whether you would classify this as a bug or an undocumented feature, but there's inconsistent behavior between how global vars and hashtables handle the -uN and -z switches.

Hashtables items created using the -u or -z switch aren't written to disk unless /hsave uses the -u switch. However /saveini does not follow that same behavior with global vars except during ON EXIT.

This does not write the dash_u and dash_z hashtable items to disk:

Code:
//hfree testvar | hmake -s testvar | hadd -u60 testvar dash_u 1 | hadd -z testvar dash_z 60 | hadd testvar test | hsave -su testvar test.dat



but saveini does write global variables created using the -u and -z switches:

Code:
//var %varsini $readini($mircini,nt,rfiles,n1) | set -u600 %testvar1 1 | set -z %testvar2 600 | saveini | filter -fs $qt(%varsini) *testvar*



If you then quit mIRC before these variables unset, it does skip them during the final ON EXIT diskwrite. However that leaves open a window of opportunity for mirc to crash between the last of the interval saveini diskwrites and the final ON EXIT diskwrite. This leaves the next ON START event seeing these as if they're permanent globals. It is true that scripts can do a safety unset of these variables during ON START, but scriptors may not be aware they need to do that to safeguard against a rare crash.

Top
#264133 - 01/11/18 08:29 PM Re: /saveini writing temp global vars [Re: maroon]
maroon Offline
Hoopy frood

Registered: 12/01/04
Posts: 969
To restate the issue, /saveini and mIRC's saving at intervals both skip all variables where .local is $true. They should also skip writing variables whose .secs is not zero.

This is based on the assumption that the only purpose of mIRC's occasional saving to disk is to defend against a crash where ON EXIT isn't able to save-to-disk the variables that need to be seen by the next ON START. Normally, /saveini guarantees that things get written to disk that need to be written, but in the case of -e -z and -uN, it guarantees that things are written to disk that shouldn't be seen by ON START the next time you run the client.

From what I can tell, -e is the same as -u2147483647, and -z also sets the -u2147483647 switch along with a countdown property for which we don't have a .prop. So, if saving to vars.ini ignores everything with a non-zero .secs value, restarting mIRC after a crash won't see the -zeuN temporary globals it shouldn't see. Note to self, leave a note to the executor of my estate to make a bug report in 68 years when a -e variable unsets prior to exit.

Top
#264171 - 06/11/18 11:53 AM Re: /saveini writing temp global vars [Re: maroon]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 4295
Loc: London, UK
This just reflects what scripters asked for at the time each feature was implemented. I can see scripters asking for either behaviour ie. mIRC saving all current variables or only non-temporary variables.

That said, /saveini applies to hundreds of settings while /hsave is specifically designed for hash tables. They are not the same type of feature. In addition, variables are saved automatically in many different situations, eg. closing the script editor. So you cannot have a switch for that. My guess is that it was simply decided long ago that all variables should be saved, regardless of whether they were temporary or not.

Perhaps a better implementation for temporary %variables would have been to save an expiry timestamp for each variable. This would probably require a separate ini/mrc file. That way, even if mIRC crashed, the timestamped variable would persist until it actually timed out, even if you exited/restarted mIRC multiple times.

Top
#264176 - 06/11/18 06:25 PM Re: /saveini writing temp global vars [Re: Khaled]
maroon Offline
Hoopy frood

Registered: 12/01/04
Posts: 969
I see the only purpose of interval flushing to mirc.ini being to preserve changes that the next ON START needs to see, and to not see things it shouldn't. While saveini might deal with hundreds of settings, I don't think the other settings are things written to mirc.ini in a way that a crash could make ON START act upon things it shouldn't. It's not like ON START loads the online timer value from mirc.ini while depending on ON EXIT to clear it to zero.

The different implementation you speak of, that would be changing the way things happen during ON START after both normal exits and crashes, and might be a reason to create a new switch for that behavior for just those variables. I'm not seeing how it breaks a script if temp globals are no longer morphed into permanent globals after a crash.

That new switch would also need to preserve other settings like /inc -c or the -z switch, for which there's not a current $var().prop to know them. It would need to be kept in a different file instead of the same .ini under a different [section], due to people saving their vars.ini to vars.dat where it no longer has [sections].

Top
#264180 - 07/11/18 09:49 AM Re: /saveini writing temp global vars [Re: maroon]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 4295
Loc: London, UK
Quote:
I see the only purpose of interval flushing to mirc.ini being to preserve changes that the next ON START needs to see, and to not see things it shouldn't.

That does seem to be a reasonable assumption.

However, if you look back through versions.txt, you can see that /set -uN, /saveini, and $var() were all added at different times. So there was a time when scripters may have wanted access to the list of all active variables and could only find them in the variables file. That is a long time ago though.

On the other hand, even today, a DLL developer could choose to trigger /saveini and then read the variables file to retrieve a list of the currently active variables. It may not be good coding, or make great sense, but scripters often use the scripting language in ways that I do not expect.

I agree with your suggestion - it would only take a minute to change the behaviour - but considering it has been in place for twenty years...

Top
#264181 - 07/11/18 10:39 AM Re: /saveini writing temp global vars [Re: Khaled]
Protopia Offline
Fjord artisan

Registered: 30/08/03
Posts: 216
Loc: UK
Originally Posted By: Khaled
Quote:
I see the only purpose of interval flushing to mirc.ini being to preserve changes that the next ON START needs to see, and to not see things it shouldn't.

That does seem to be a reasonable assumption.

However, if you look back through versions.txt, you can see that /set -uN, /saveini, and $var() were all added at different times. So there was a time when scripters may have wanted access to the list of all active variables and could only find them in the variables file. That is a long time ago though.

On the other hand, even today, a DLL developer could choose to trigger /saveini and then read the variables file to retrieve a list of the currently active variables. It may not be good coding, or make great sense, but scripters often use the scripting language in ways that I do not expect.

I agree with your suggestion - it would only take a minute to change the behaviour - but considering it has been in place for twenty years...

I guess this is another example of trying to make a judgement about whether scripters (and now DLL writers) will have used mIRC in a specific way and whether a change would therefore break their code.

Personally I think it highly unlikely that DLL writers would code to get access to variables in this way - for example I am not sure how they would determine the file location for the ini files that holds this - but I suppose it is vaguely possible, and as Khaled says if your philosophy is to preserve backward compatibility even for the most unlikely use cases, then that makes changing any existing behaviours very difficult.

Top
#264182 - 07/11/18 12:17 PM Re: /saveini writing temp global vars [Re: Khaled]
maroon Offline
Hoopy frood

Registered: 12/01/04
Posts: 969
ok how about a compromise. A new setting in Alt+O giving the option to change the behavior of the background interval save, while /saveini could still do the old behavior by default so the crazy DLL could poke the bear. Then /saveini could have a switch to override the default to make it do the behavior that won't tell lies to ON START.

Top
#264183 - 07/11/18 12:22 PM Re: /saveini writing temp global vars [Re: maroon]
Protopia Offline
Fjord artisan

Registered: 30/08/03
Posts: 216
Loc: UK
Originally Posted By: maroon
ok how about a compromise. A new setting in Alt+O giving the option to change the behavior of the background interval save, while /saveini could still do the old behavior by default so the crazy DLL could poke the bear. Then /saveini could have a switch to override the default to make it do the behavior that won't tell lies to ON START.

That sounds reasonable to me, but obviously Khaled's choice.

Top
#264199 - 08/11/18 05:33 PM Re: /saveini writing temp global vars [Re: maroon]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 4295
Loc: London, UK
Quote:
ok how about a compromise. A new setting in Alt+O giving the option to change the behavior of the background interval save, while /saveini could still do the old behavior by default so the crazy DLL could poke the bear. Then /saveini could have a switch to override the default to make it do the behavior that won't tell lies to ON START.

I would much rather mIRC behaved consistently. Apart from that, I have mentioned in the past that I am no longer adding micro-options to the options dialog that change how mIRC behaves in small and subtle ways. If anything, I would much rather remove options like these from the options dialog in order to streamline it and make the interface, features, etc. more predictable and easier to manage and code for.

The only real option at this point is to either keep the current behaviour or to change it.

Top
#264201 - 08/11/18 08:18 PM Re: /saveini writing temp global vars [Re: Khaled]
Raccoon Online
Hoopy frood

Registered: 18/02/03
Posts: 2501
Agreed about the options dialog. Less is more. Navigating users to the options they want grows ever more tedious.

(IF you were to get rather inspired, Khaled, and plan to do a revamp for mIRC 8.x ... I'd like to propose adopting the same method as Firefox's 'about:config'. One big hash table of all settings in a format like: 'mirc.dde.enabled 1' and 'mirc.mnick Raccoon' and 'control.ignore.1 *!~*@*.tk -tdip'. That way not every setting requires a GUI element and can be accessed via Advanced Options, keeping mIRC simple but flexible to power-users.)
_________________________
doin´┐Ż things a particle can

Top
#264252 - 12/11/18 09:06 AM Re: /saveini writing temp global vars [Re: Khaled]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 4295
Loc: London, UK
Okay, the more I look at this, the more I think changing the behaviour will be an issue. Another example is, if mIRC does not save temporary variables to the variables file and a script issues /load -rv, for whatever reason, all temporary variables will cease to exist. There may be other side-effects that are difficult to foresee.

The only solution I can think of is to add a keyword to the variables file, just like "alias", "menu", and so on in remote scripts, that tells mIRC to unset a variable on a restart. So, we could use "unset %var" on a single line, which would appear in the variables list as a separate item to the %var definition. If mIRC sees this on a restart, it knows that it should unset the %var because it was a temporary variable.

This would also allow "unset -switches %var" where -switches could specify other behaviours, such as timing out only after a certain point in time, so you could exit/restart mIRC and the variable would be preserved until it is actually set to timeout.

As far as I can see, adding an "unset" keyword would be backwards compatible as older versions of mIRC would just ignore the line.

Top
#264258 - 12/11/18 06:45 PM Re: /saveini writing temp global vars [Re: Khaled]
maroon Offline
Hoopy frood

Registered: 12/01/04
Posts: 969
Ok, I'd never thought of using -rv to swap vars files. I doubt it would be used much if at all, because of the effects it would have on the variables created by other scripts. But if it's an issue that all -uN or -e variables cease to exist, it should also be an issue that some normal global vars also cease to exist, or revert back to their value at whatever point when they'd been saveini'ed to disk.

To test this, I created both a normal global var, and one having -u99999 switch, then I used -rv to change the file to use an empty foobar.ini, and found that neither the normal or temp global variables were written to disk to the old file as I used /load -rv. I then tried to see how long it took for mIRC to write the permanent or global variables to disk, in an environment where the scripts editor wasn't opened and no scripts were executing the /saveini command. After 4 hours neither global variable was written. That is, until I used alt+R to open the scripts editor to the 'remote' tab without doing editing of the script, and immediately the vars.ini gets updated.

Unless you meant that someone would execute saveini to flush the vars.ini to disk prior to using load -rv, then planned to use load -rv again later to restore their variables. In which case they're trading one problem for another, because instead of missing/wrong permanent globals vanishing even though they existed for 4 hours without being written to disk, the /saveini now causes temp globals written in stone as if they were global, as well as the globals written in stone as if they had not used -u -z -e or -c. It would make sense that load -rv would trigger a flush to disk for the old filename, so the 4-hour-old permanent global can get written to disk, as this is similar to an EXIT event as far as the variables are concerned.

But regardless, allowing vars.ini to contain info about variables so ON START can accurately sort things out is nice. That new behavior would be the only way I know for discovering whether a global variable is using the -c or -z flags, as there are no .props to tell us.

Code:
//inc -scu5 %x | set -sz %z 5 | saveini


Since global variables are so important, there should probably be some kind of flag to trigger a disk write to the vars file, after a reasonable interval, if there have been global variables created or deleted. The -c or -z increments and decrements shouldn't need to trigger such a diskwrite, since the vars file containing a timestamp would let ON START accurately restore variables without the updated diskwrite.

Top