WAD Output redirection in tcexit looses data

#1
Hi there,

in tcexit.bat I save the current directories with
cdd /a > c:\Data\Tools\drives.dat
cd >> c:\Data\Tools\drives.dat​
and load them in tcstart.bat. Most of the time this works and generates
C:\Temp
D:\
E:\
C:\Temp​
in drives.dat. But every once in a while only
C:\Temp
D:\
E:\​
is in the drives.dat file. It looks like tcc could not flush the file or the last line gets lost.
Inserting delay /m 100 at the end of tcexit.bat did not help.
Is this a known bug and what is the workaround?

Edit: The bug shows only when I use the close button on TCMD, with 'exit' it always works

Best regards
Josef
 

rconn

Administrator
Staff member
May 14, 2008
10,320
93
#2
Not a bug (or at least, not a TCC bug). Windows only gives processes a limited amount of time before killing them when you use the close button, and depending on the speed of your system and what else is going on, it may not be enough time to finish all of your TCExit processing.

There's nothing I can do about it in TCC.
 
#9
That would work Maarten, since Alt+F4 never reaches TC[C|MD]. It is caught by Windows first.
To bypass the regular behaviour of Alt-F4, you will also have to add an entry to your TCMD.ini:
Code:
[4NT]
NormalKey=Alt-F4
This affects only TCC /TCMD; in otther applications (e.g. notepad.exe) Alt-F4 will still have the usual behaviour.
More on NormalKey here ...
 
Apr 13, 2010
216
2
57
The Hague
#12
Nothing complicated. If you have a bunch of apps open and at the end of the day you just repeatedly type Alt+F4 to close everything TC will not receive the focus and still be closed by Windows in the unintended way. Even if TCC is the only open app.

But the point is your original solution is a valid one. Although not fail-safe, it is a significant improvement.
 
Apr 13, 2010
216
2
57
The Hague
#14
Put a pause statement in your TCExit.
Then try closing the console with Alt-F4.
If it had the focus it will wait indefinitely. If not you will see Windows killing it after a couple of seconds.
 
Apr 13, 2010
216
2
57
The Hague
#15
@Maarten: from the manual "Deassigns a general input key in order to disable the usual meaning of the key and/or make it available for keystroke aliases.". The way I understand this is that "normalkey=Alt-F4" would take away any special *input key* meaning, if it had any. Which it doesn't *within TC*.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,499
45
Albuquerque, NM
prospero.unm.edu
#16
Put a pause statement in your TCExit.
Then try closing the console with Alt-F4.
If it had the focus it will wait indefinitely. If not you will see Windows killing it after a couple of seconds.
I'm not sure what you're saying here. PAUSE waits for you to press a key; Alt-F4 is a key. Any further commands after the PAUSE are executed after Alt-F4.

Or are you maybe using Windows 10, with its newfangled console?
 
#18
@Maarten: from the manual "Deassigns a general input key in order to disable the usual meaning of the key and/or make it available for keystroke aliases.". The way I understand this is that "normalkey=Alt-F4" would take away any special *input key* meaning, if it had any. Which it doesn't *within TC*.
I know. But as you were having trouble somehow with the @@Alt-F4 alias (
Alt+F4 never reaches TC[C|MD]. It is caught by Windows first.
), I suggested the NormalKey option.
 
Apr 13, 2010
216
2
57
The Hague
#20
This thread started because a user was losing data being written by TCExit. Rex contributed that when Windows is in control of TC[C|MD]'s exit there is limited time available to do stuff in TCExit. Only if the user issues the exit command is there unlimited time for TCExit to do its thing.

Maarten suggested a keystroke alias for Alt-F4 to - at least in that case - make TC be in control of the exit. I merely pointed out that, although an improvement, it would only be an improvement if TC had the focus at the moment of typing Alt-F4.
 
Apr 13, 2010
216
2
57
The Hague
#21
If you try my suggested experiment (@ Maarten: the pause creates a TCExit that takes too long and causes Windows to intervene, which is what we're trying to demonstrate here) you'll get a feel for how often TC doesn't have the opportunity to help us with the keystroke alias.
 
Last edited:
Apr 13, 2010
216
2
57
The Hague
#22
So, returning to the original problem. The user would have been better answered if we had simply pointed out that TCExit is generally not a great place to do last minute state saving. Not only is it vulnerable to interruptions by Windows, also - and even in the case of a normal exit with TC at the helm - if you open more than one console you invariably run into the problem of one process overwriting the state of another. (Yes, you could use a host of semaphores, mutexes and critical sections, but that would only stimulate the users to add even more code to TCExit, thus increasing the first risk!)

Regards, DJ.
 
#25
DEFER doesn't sound good. It would require TCC to still be running after TCEXIT. If I understand this thread correctly, the whole problem is that TCC is getting clobbered before TCEXIT has finished ... yes/no?
 
Apr 13, 2010
216
2
57
The Hague
#28
Defer will not work. It doesn't work using either Alt-F4 or clicking 'x'. That is as expected because the process executing the deferred commands is not in control (as was established above) and will simply be murdered by Windows after a couple of secs. What surprised me is that it also doesn't work if you exit TC with an exit command. In that case TC is in control of shutting down and could ask all consoles to check whether there is still work to be done. Apparently it doesn't ask, so it doesn't know and proceeds to kill them.

What would work is starting a batch - wait for it - if and only if you have the auto-attach-console option OFF and use tcc's /ix ! Omitting one is enough to create a monster, and it's not Halloween yet.
 
#29
Hi there,

in tcexit.bat I save the current directories with
cdd /a > c:\Data\Tools\drives.dat
cd >> c:\Data\Tools\drives.dat​
How about putting the cdd /a > c:\Data\Tools\drives.dat into the POST_EXEC alias?

I realize that this would save the current directories on all of your drives every time after returning from a command and before displaying the prompt, but it would get the information that you want, albiet not on the closing of TCMD.

Also, this only gets updated at the command prompt.

Joe
 
Apr 13, 2010
216
2
57
The Hague
#30
Before answering Joe's question, I would like to remind the readers that keyboard commands and mouse clicks are not the only reason TC shuts down. Windows itself too, sometimes decides to shutdown or restart. Network admin actions, e.g, or simply inactivity, are events that once detected give TC precious little time to finish up either TCExit or anything else it started!

BTW, these last remarks are also relevant to ON CLOSE, -SUSPEND and -SHUTDOWN.

So, in answer to Joe's questions: if you must regularly update persisted state, you can do that in TCExit, but:
1) it should be short and fast - always.
2) write once for all closing consoles, not every single closing console

ad 1) If your example is the only thing you would like to do in TCExit, at first glance is seems simple enough that it might reliably work. At second glance I realized a pitfall that makes this statement not universally true (Come to think of it, what is?) Disk drives, whether builtin or as mapped network drives, are often spun down to save energy; your code is no problem if the're all buzzing - but no go if one of them sleeps. It's a great example that nicely demonstrates the vulnerability of the TCExit process.

BTW, restoring (=changing) the current directory in TCStart is not considered good practice. It will effectively defeat any attempt to set the current directory to something useful with start or hyperlinks.

ad 2) Can be approximated by simply adding the following line to your TCExit
Code:
:: Here code that executes for all consoles closing.

:: This tests for the remaining number of shells spawned by our primary shell.
if %_shells gt 0 quit

:: The test above is fast and should thin out the possibilities.
:: Here, put code that should executed by primary shells only.
:: Note that still there can be more than one running in parallel.

:: To find that last console,...
tasklist tcc* > clip:
if %@lines[clip:] ne 0 quit

:: Here we're the last of the Mohicans.
But why not move the work to TCStart instead of TCExit? You can find the state you want in the dir-history which is already maintained and written for you. (set option SaveOnEntry) At startup, search the dir-history backwards until you have found what the last current directory was for each drive you want to restore. No need to redundantly write anything.

[Edit] There is a practical problem with my proposed solution. It is not full proof, but still a huge improvement. The problem is out of scope of this thread.

Regards, DJ
 
Last edited: