Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Thoughts on how to devise a queryable win32 service

by noslenj123 (Scribe)
on Feb 08, 2005 at 22:15 UTC ( [id://429243]=perlquestion: print w/replies, xml ) Need Help??

noslenj123 has asked for the wisdom of the Perl Monks concerning the following question:

I have services running on many windows boxes. At times they either get stopped or are running but not responding. I want to build a script that will open a socket to each service and have that service respond to commands.

So each service will generally be running processes in a loop. At the same time it will need to respond to socket connections and respond accordingly(even if they are running a task). This is cutting edge for me as I learn more and more perl.

My thought is to have the service start a new thread that handles socket connections and responses while the main thread runs the looping processes. Would it be hard for it to view some main thread variables to obtain status?

I'm also noticing modules like Win32-Process and Win32-Job and wondering if they might be more appropriate and/or easier for them to determine status and respond.

Does anyone have any thoughts on a direction for this task?

  • Comment on Thoughts on how to devise a queryable win32 service

Replies are listed 'Best First'.
Re: Thoughts on how to devise a queryable win32 service
by cowboy (Friar) on Feb 08, 2005 at 22:24 UTC

      I recently looked at POE to perform heavy processing for multiple tasks at the same time. I was impressed. However, I hit a brick wall since some of the important modules of POE would not compile and/or install on Win32 (according to activestate testing results, and some personal attempts) due to the lack of adequate support of forking on win32. What I needed was Wheel::Run and POE::Component::Child and that turned out to be a dead-end for me. Anyone with more experience on Win32 and POE?

      Right now, I'm playing with threading and IO::Socket to perform these tasks.

      Hope this helps.

Re: Thoughts on how to devise a queryable win32 service
by BrowserUk (Patriarch) on Feb 09, 2005 at 04:49 UTC
    My thought is to have the service start a new thread that handles socket connections and responses while the main thread runs the looping processes. Would it be hard for it to view some main thread variables to obtain status?

    No, no problem at all. Just share the variables that you want the status thread to be able to see, and add:

    my $sharedVar : shared; .... { lock( $sharedVar ); #do stuff with $sharedVar }

    around each access to those shared variables in both pieces of code.

    If your going to use a package like IO::Socket::INET to provide the communications within the status thread, require it within that thread rather than useing it at the top of the script.

    In essence that is all there is to it.

    There are some limitations about what types of variable can be shared--filehandles (hackable) and objects or tied vars (not easily hackable)--but that needn't be a great limitation.

    Does anyone have any thoughts on a direction for this task?

    From your description so far, using a thread would seem the ideal route to me.

    Of course, the devil is in the detail--in this case, the detail of exactly what information you want to share between the threads.


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
      Your Monkness,

      I apparently don't understand a scoping or access issue with trying to access my main program's variable from the thread subroutine. I have:

      use strict; use Thread; my $time : shared; my $t = Thread->new(\&listener,\$time); while (1) { $time = localtime; print $time,"\n"; sleep 1; } sub listener { my $time_ref = shift; while (1) { { lock($$time_ref); print "\tThread time: [$time]\n"; print "\tThread time: [$main::time]\n"; print "\tThread time: [$$time_ref]\n"; } sleep 3; } }
      Which prints out:

      Wed Feb 9 08:06:02 2005 Thread time: [] Thread time: [] Thread time: [] Wed Feb 9 08:06:03 2005 Wed Feb 9 08:06:04 2005 Wed Feb 9 08:06:05 2005 Thread time: [] Thread time: [] Thread time: [] Wed Feb 9 08:06:06 2005
      Indicating to me that the thread only sees the initial value like it has it's own copy. Is that right? How do I access the main threads $time var? Hmmmmm.

        You had me going there for a few seconds--everything in your program seemed legit at first glance;

        Problems:

        1. You are useing "Thread": Don't!

          The Thread module relates to an early attempt at threading in Perl (called perl5005threads). These were deemed a failure and are "going away" in the next release.

          It has been superceded by Ithreads via the threads module.

          It requires at least 5.7.?, but you should not try to use them with any version < 5.8.4 -- get 5.8.6 if you can.

        2. You also need to be using threads::shared if you wish to share variables between threads.
        3. You don't need to pass a reference to $time into your thread sub, once it is shared, it can be seen from any thread (provided it was declared before the thread sub is instantiated.
        4. For correctness, you should be locking your shared variables in both (all) threads.

          In (my) reality, if you are running in a single CPU machine, read references do not appear to need locks be applied as only one thread can be running at a time, but if you move the code without locks to a multiprocessor machine you would likely get bitten.

          In theory, even on a single processor machine, it is possible that one thread could be in the process of writing to a shared variable and have not completed the update when it gets suspended. If it did not apply locks, or another thread reading it does not apply them (and thereby get suspended until teh write is completed), then the other thread could read a partially updated variable that is not in an internally coherent state and get bad data or even segfault.

          To date, try as hard as I might, even running long running, backtracking regexes on huge shared strings, I have never been able to make this happen.

          ( For the pedantic: The above statement is only true: on my single processor, win32 machine; in my house; whilst I've been watching; etc. etc. etc.....Yet! ;)

        use strict; use threads; use threads::shared; my $time : shared; sub listener { my $array_ref = shift; while (1) { { lock $time; print "\tThread time: [$time]\n"; } { lock($array_ref); print "\tThread time: [@$array_ref]\n"; } sleep 3; } } my @array : shared; my $t = threads->new( \&listener, \@array ); while (1) { { lock $time; $time = localtime; } print $time,"\n"; { lock @array; push @array, $time; } sleep 1; } __END__ [16:09:17.53] P:\test>429405 Wed Feb 9 16:09:31 2005 Thread time: [Wed Feb 9 16:09:31 2005] Thread time: [] Wed Feb 9 16:09:32 2005 Wed Feb 9 16:09:33 2005 Thread time: [Wed Feb 9 16:09:33 2005] Thread time: [Wed Feb 9 16:09:31 2005 Wed Feb 9 16:09:32 200 +5 Wed Feb 9 16:09:33 2005] Wed Feb 9 16:09:34 2005 Wed Feb 9 16:09:35 2005 Wed Feb 9 16:09:36 2005 Terminating on signal SIGINT(2)

        I switched your code around a bit not because there was anything wrong with the ordering, but to allow me to demonstrate a couple of points.

        I've stopped passing the scalar ref to the sub and am passing a reference to an array that is also updated in the main thread.

        Because $time is visible to your listener() sub, it is accessible, via closure in the normal way, without being explicitly passed it to the thread.

        The array however, was not existing when the sub was declared, so it must be passed explicitly.

        Basically, all the normal perl scoping rules apply--once you are using the correct modules :) I should have mentioned that before. Sorry!


        Examine what is said, not who speaks.
        Silence betokens consent.
        Love the truth but pardon error.
        In my humility I guess I don't know the difference between 'Thread' and 'threads'. After shifting the code to use 'threads' and 'threads::shared', I am able to access my variable. What the heck is the 'Thread' module for then?
Re: Thoughts on how to devise a queryable win32 service
by noslenj123 (Scribe) on Feb 09, 2005 at 14:00 UTC
    Thanks o wise ones! I have looked at POE before and have not undertaken the learning curve and found the documentation, well, open sourc'ish...lol

    I will go down the enlightened path of using a thread as I really only have to access a string var in the main code. Sounds easy enough given BrowserUk's description.

    $OP = 'Most Humbly Bows';

      Might be completely OT (apologies if it is) - but you mentioned Win32-Process etc. Have you looked at WMI? You can find out just about anything -hardware, processes, installed applications, services (and do things e.g. spawn processes, etc.) on the local machine or remote machines.

      Start at

      Microsoft WMI docs
      I haven't use WMI from Perl, but I have in Tcl using Tcom, so I'm sure Perl can do it!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://429243]
Approved by Tanktalus
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (9)
As of 2024-04-19 07:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found