|Keep It Simple, Stupid|
Restarting script without losing handlesby athomason (Curate)
|on Aug 21, 2002 at 18:46 UTC||Need Help??|
athomason has asked for the
wisdom of the Perl Monks concerning the following question:
I'm working on a TCP proxy server that watches text traffic incoming on two sockets and occassionally injects its own data, based on regex matches on the stream data. The interesting part is that the rules and actions aren't predefined: as the program is monitoring the sockets it needs to take input from somewhere (mabye STDIN) concerning 1) the regexen that determine action and 2) the actions themselves (probably as anonymous subs). The connections can't be dropped (so the script can't just be killed and reloaded), though a lag of a few seconds after adding a rule is acceptable (see further down why that might be useful).
Input from STDIN is implicitly trusted, so I don't feel wholly unjustified eval'ing what I read there (though it would require care, for sure), but I also need the stuff that's added to be persistent (i.e., last bewteen proxy sessions). The simplest thing that comes to mind is Data::Dumper'ing the ruleset to a file (or DATA, even) and eval'ing that when the script starts up. New rules added during runtime would be added to the ruleset and written out to disk for later recovery. There are a number of hacks required to go that route, though. For one, I anticipate needing global state variables that are set and used in the rules; while I could store a mini-symbol table as %state or some such, it sure seems that would be adding unnecessary clutter.
Ideally, I could put all the matching logic in the script itself instead, and somehow recompile and restart it without dropping the connection. Though there would be a delay as it recompiled, I could live with it. This strategy would also avoid the thoroughly unpleasant business of eval'ing in a network server. I had an idea that exec would be useful for this purpose, since I seem to recall filehandles are propogated to the transferee (like fork does). However, I wouldn't swear to it, and I don't see a mention of that in the perlfunc. Besides, if I do exec myself, how do I recover the handles in the fresh script? I wouldn't think they would be automagically named the same, though I confess I haven't tried it yet.
If exec doesn't work that way, can anyone think of another way to recompile without losing the handles? I wouldn't mind having the instruction pointer reset, since I can get back to the processing loop easily enough if the handles are already established.
Read more below for the bit I have now which doesn't do any of the persistence stuff. Hopefully it can clear up any confusion about how I'm doing matching and injection. So far the code is basically just the non-forking TCP server example from perlipc modified to proxy between the incoming client and a predefined remote host, with a few rules added in. It does have an issue (less interesting, for now) where it doesn't flush the handles correctly, in case anybody runs across it. Hitting <ENTER> a few times seems to work around it, sort of.