in reply to multiple infinitive loops

This is what im trying to archieve

use strict; use Win32::OLE qw(in); Win32::OLE->Option("Warn"=>3); use threads qw[ async ]; sub check_1 { my $query = "SELECT * FROM __InstanceCreationEvent WHERE TargetIns +tance ISA 'Win32_NTLogEvent' "; my $wbemloc = new Win32::OLE("WbemScripting.SWbemLocator"); $wbemloc->{Security_}->{Privileges}->AddAsString("SeSecurityPrivil +ege"); my $wbemsvc = $wbemloc->ConnectServer(".", "root/cimv2"); $wbemsvc->{Security_}->{ImpersonationLevel} = 3; my $wbemevtsrc = $wbemsvc->ExecNotificationQuery($query); while (1) { my $wbemobj = $wbemevtsrc->NextEvent(); my $msg = $wbemobj->{TargetInstance}->{Message}; $msg =~ s/\t//g; my @array = split(/\r\n/,$msg); my $tst = join(';',@array); $tst =~ s/;;/;/g; print $tst."\n"; } } sub check_2 { my $query = "SELECT * FROM __InstanceDeletionEvent WHERE TargetIns +tance ISA 'Win32_NTLogEvent' "; my $wbemloc = new Win32::OLE("WbemScripting.SWbemLocator"); $wbemloc->{Security_}->{Privileges}->AddAsString("SeSecurityPrivil +ege"); my $wbemsvc = $wbemloc->ConnectServer(".", "root/cimv2"); $wbemsvc->{Security_}->{ImpersonationLevel} = 3; my $wbemevtsrc = $wbemsvc->ExecNotificationQuery($query); while (1) { my $wbemobj = $wbemevtsrc->NextEvent(); my $msg = $wbemobj->{TargetInstance}->{Message}; $msg =~ s/\t//g; my @array = split(/\r\n/,$msg); my $tst = join(';',@array); $tst =~ s/;;/;/g; print $tst."\n"; } } async \&check_1; check_2;



Its locking at my $wbemobj = $wbemevtsrc->NextEvent();
The check_2 will not be started :(

Many Thanks,
Oscar

Replies are listed 'Best First'.
Re^2: multiple infinitive loops
by BrowserUk (Patriarch) on Oct 06, 2004 at 19:15 UTC

    A personal plee, ignore at will. Please insert some horizontal whitespace (and use proper indentation, though I realise that that can get screwed through posting/cutting/pasting).

    sub check_1 { my $query = " SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA'Win32_NTLogEvent' "; my $wbemloc = new Win32::OLE( "WbemScripting.SWbemLocator" ); $wbemloc->{ Security_ }{ Privileges } ->AddAsString( "SeSecurityPrivilege" ); my $wbemsvc = $wbemloc->ConnectServer( ".", "root/cimv2" ); $wbemsvc->{ Security_ }{ ImpersonationLevel } = 3; my $wbemevtsrc = $wbemsvc->ExecNotificationQuery( $query ); while( 1 ) { my $wbemobj = $wbemevtsrc->NextEvent(); my $msg = $wbemobj->{ TargetInstance }{ Message }; $msg =~ s/\t//g; my @array = split( /\r\n/, $msg ); my $tst = join( ';', @array ); $tst =~ s/;;/;/g; print $tst."\n"; } }

    More readable than above? I had to resort to sorting the source to determine that check_1 and check_2 were identical.

    Which brings me to my second point. Cut&paste code is bad (bad,bad;), and completely unnecessary. The whole point of subroutines is that you can call them twice or more. (Caveat: closures can complicate this!)

    This works fine.

    #! perl -slw use strict; use threads qw[ async ]; sub sub1 { my $no = shift; while(1) { print "in sub $no"; select undef, undef, undef, 0.1; } } async \&sub1, 1; ## Param = '1' sub1( 2 ); ## Param = '2' __END__ P:\test>397011 in sub 2 in sub 1 in sub 2 in sub 1 in sub 2 in sub 1 Terminating on signal SIGINT(2)

    And that brings up the third point which is speculative because I don't have the "WbemScripting.SWbemLocator" (as far as I am aware) in order to verify this.

    Many OLE .dll's use what I believe is called the 'apartment' model. The in's and out's of this are complicated, off-topic for this place, and I'm not sure I remember them correctly (if I ever did). Breifly, there are various ways of building DLLs, some of which allow that DLL to be called from as many processes, and as many threads within those processes as you like. Ie. they are fully reentrant. Others can only be entered once from within a given process. There are other variations as well--see MSDN for more/better/accurate information.

    The upshot is that it may be that the DLL that provides the OLE object you are calling is not compatible with threading. It would be a good thing to know, before continuing to try do what your doing, if this is the case or not. The best I can suggest is that you consult the docs, or vendor, before expending more energy trying to solve this.

    Alternatively, if you have and know VB, then try doing what your doing from (minimally) from there. If you hang up there too, then you probably have your answer.

    Of course, it may be that your real code doesn't try to access the same identical object/event loop concurrently, and this is just more sample code.

    Ultimately, sample code rarely helps solve real problems.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      Thanks for your post
      I am going to try VB tommorow when I get my cd in from work.., then it's M$->M$ combination which probally work, and if not, then the problem is the COM itself... which im not intended to rewrite :p

      Copy/pasting the code was merely for a understanding to people on how I implemented the Win32::Ole thing...

      again, exploring this area, nothing more :p

      Thanks for all your help

      Oscar
Re^2: multiple infinitive loops
by DaveH (Monk) on Oct 06, 2004 at 19:01 UTC

    I think you may be onto a loser trying to combine Perl threads and COM (Win32::OLE), unless this has been improved recently. See this article on the ActiveState Win32 mailing list (the post is over a year old - things have moved on a tad since - but the error shown matched the one I received). Dispite this, using fork as shown by Plankton in the earlier example does appear to work for me (i.e. it executes both subs, which is odd, since fork on win32 is implemented with threads...).

    my $pid; if( $pid = fork ) { check_1(); } elsif ( defined $pid ) { check_2(); }

    Hope the mailing list reference helps.

    Cheers,

    -- Dave :-)


    $q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
      hey dave,

      yeah I tried the fork :) but with no luck

      actually the app is getting pretty unpredicatable using this method (i.e.) one time is does it work correctly and the other time it doesn't :D

      I think the win32::ole is a little bit of a P.I.T.A. and I might switch over to M$ vb to check things...,

      Thanks for your input
      Oscar
Re^2: multiple infinitive loops
by kelan (Deacon) on Oct 06, 2004 at 20:41 UTC

    Here's a simple way to do it with POE. Keep in mind that there will be at minimum a one second delay before each check for a new event. More importantly, if the NextEvent() calls block (which I'm guessing they do from your code), you could wait longer than one second on a given check, meanwhile events from the other generator could be happening. That's the trouble with blocking calls. I didn't feel like copying 90% of your code, so you'll need to replace the ...'s with the relevant portions.

    #!/usr/bin/perl use strict; use warnings; use POE; POE::Session->create( inline_states => { _start => \&init, check_creation => \&check_creation, check_deletion => \&check_deletion, }, ); $poe_kernel->run(); exit 0; sub init { my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; # make creation event logger thingie $query = ...; # the creation one ... $heap->{ creator } = $wbemsvc->ExecNotificationQuery( $query ); # make deletion event logger thingie $query = ...; # the deletion one ... $heap->{ deletor } = $wbemsvc->ExecNotificationQuery( $query ); $kernel->delay_set( check_creation => 1 ); $kernel->delay_set( check_deletion => 1 ); } sub check_creation { my ( $kernel, $heap ); my $wbeobj = $heap->{ creator }->NextEvent(); my $msg = $wbeobj->{ TargetInstance }->{ Message }; # ... do the message stuff here $kernel->delay_set( check_creation => 1 ); } sub check_deletion { my ( $kernel, $heap ); my $wbeobj = $heap->{ deletor }->NextEvent(); my $msg = $wbeobj->{ TargetInstance }->{ Message }; # ... do the message stuff here $kernel->delay_set( check_deletion => 1 ); }