| 728 | | # TODO: Clean up this comment block. |
|---|
| 729 | | # This function should do the following: |
|---|
| 730 | | # - Initialize all drivers with starting state. |
|---|
| 731 | | # - "Drive" each driver, one-by-one. |
|---|
| 732 | | # - Collect any integrity violations found, with offending |
|---|
| 733 | | # state information. |
|---|
| 734 | | # |
|---|
| 735 | | # Notes: |
|---|
| 736 | | # This function will eventually sit in a sub-thread, allowing the parent |
|---|
| 737 | | # thread to return without any delay. It is expected that the Manager |
|---|
| 738 | | # would then subsequently call a getStatus() operation, in order to |
|---|
| 739 | | # then poll for any new violations found. |
|---|
| 740 | | # |
|---|
| 741 | | # TODO: We need to create a fault reporting mechanism, in order |
|---|
| 742 | | # to properly deal with exceptions/faults that occur within this |
|---|
| 743 | | # thread. |
|---|
| 744 | | $thread = async { |
|---|
| 745 | | threads->yield(); |
|---|
| 746 | | |
|---|
| 747 | | # Trap all faults that may occur from these asynchronous operations. |
|---|
| 748 | | eval { |
|---|
| 749 | | |
|---|
| 750 | | ################################### |
|---|
| 751 | | ### Driver Initialization Phase ### |
|---|
| 752 | | ################################### |
|---|
| 753 | | |
|---|
| 754 | | # Initially set local integrity object to undef. |
|---|
| 755 | | my $integrity = undef; |
|---|
| 756 | | |
|---|
| 757 | | # Initially set all driver objects to undef. |
|---|
| 758 | | my $driver = undef; |
|---|
| 759 | | |
|---|
| 760 | | # Acquire lock on stored driver state. |
|---|
| 761 | | $data = _lock(); |
|---|
| 762 | | |
|---|
| 763 | | if ($PERFORM_INTEGRITY_CHECKS) { |
|---|
| 764 | | # XXX: WARNING - The $integrityState object data is NOT thread-safe |
|---|
| 765 | | # (since it relies on external data stored on the file system). |
|---|
| 766 | | # As such, do NOT try to call integrity checks on multiple, simultaneous |
|---|
| 767 | | # asynchronous threaded drivers. |
|---|
| 768 | | $integrity = thaw($integrityState); |
|---|
| 769 | | # Perform initial integrity baseline check. |
|---|
| 770 | | #print "Initializing Integrity Check...\n"; |
|---|
| 771 | | # TODO: Initialize Integrity Checks |
|---|
| 772 | | #$integrity = HoneyClient::Agent::Integrity->new(); |
|---|
| 773 | | } |
|---|
| 774 | | |
|---|
| 775 | | # Now, initialize each driver object. |
|---|
| 776 | | # Figure out which $driver object to use... |
|---|
| 777 | | my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; |
|---|
| 778 | | |
|---|
| 779 | | if (!defined($data->{$driverName}->{'state'})) { |
|---|
| 780 | | |
|---|
| 781 | | # If the driver state is undefined, then |
|---|
| 782 | | # create a new state object. |
|---|
| 783 | | $driver = $driverClass->new(); |
|---|
| 784 | | |
|---|
| 785 | | } else { |
|---|
| 786 | | # Then the driver state object is already defined, |
|---|
| 787 | | # so go ahead and reuse it. |
|---|
| 788 | | $driver = $driverClass->new( |
|---|
| 789 | | %{$data->{$driverName}->{'state'}}, |
|---|
| 790 | | ); |
|---|
| 791 | | } |
|---|
| 792 | | |
|---|
| 793 | | # Next, we make sure we have no updates, before we update |
|---|
| 794 | | # the corresponding shared memory version. |
|---|
| 795 | | $driver = _update($driver); |
|---|
| 796 | | |
|---|
| 797 | | # Once we've initialized the object, be sure to update |
|---|
| 798 | | # the corresponding shared memory version. We do this |
|---|
| 799 | | # one time before the loop starts, in case we end up |
|---|
| 800 | | # finishing before we drove anywhere. |
|---|
| 801 | | |
|---|
| 802 | | # Copy object data to shared memory. |
|---|
| 803 | | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| 804 | | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| 805 | | $data->{$driverName}->{'status'}->{'is_compromised'} = 0; |
|---|
| 806 | | $data->{$driverName}->{'status'}->{'is_running'} = 1; |
|---|
| 807 | | $data->{$driverName}->{'state'} = $driver; |
|---|
| 808 | | |
|---|
| 809 | | # XXX: Check to see if this is okay. |
|---|
| 810 | | # if ($driver->isFinished()) { |
|---|
| 811 | | # # Thread is about to finish, set the ID back to undef. |
|---|
| 812 | | # # This looks ugly, but setting it this early avoids the |
|---|
| 813 | | # # potential race condition of when the run() thread is finished |
|---|
| 814 | | # # and when updateState() checks for $driverData->{$driverName}->{'thread_id'} |
|---|
| 815 | | # # to be set to undef. |
|---|
| 816 | | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| 817 | | # } |
|---|
| 818 | | |
|---|
| 819 | | # Release lock on stored driver state. |
|---|
| 820 | | _unlock($data); |
|---|
| 821 | | |
|---|
| 822 | | ################################### |
|---|
| 823 | | ### Driver Running Phase ### |
|---|
| 824 | | ################################### |
|---|
| 825 | | |
|---|
| 826 | | # Boolean to indicate that the driver is about to transition |
|---|
| 827 | | # to a new set of targets upon the next drive() operation. |
|---|
| 828 | | my $driverTargetsChanged = 0; |
|---|
| 829 | | |
|---|
| 830 | | while (!$driver->isFinished() && !$driverTargetsChanged) { |
|---|
| 831 | | # XXX: Debug. Remove this. |
|---|
| 832 | | # We assume $driver->next() returns defined data. |
|---|
| 833 | | foreach my $resource (keys %{$driver->next()->{resources}}) { |
|---|
| 834 | | print "Using Resource: " . $resource . "\n"; |
|---|
| 835 | | } |
|---|
| 836 | | |
|---|
| 837 | | # Drive the driver for one step. |
|---|
| 838 | | # If the operation fails, then an exception will be generated. |
|---|
| 839 | | $driver->drive(); |
|---|
| 840 | | |
|---|
| 841 | | # Acquire lock on stored driver state. |
|---|
| 842 | | $data = _lock(); |
|---|
| 843 | | |
|---|
| 844 | | # Check for any additional external driver updates. |
|---|
| 845 | | $driver = _update($driver); |
|---|
| 846 | | |
|---|
| 847 | | # Check to see if our driver's targets have changed. |
|---|
| 848 | | $driverTargetsChanged = not(Compare($data->{$driverName}->{'next'}->{'targets'}, $driver->next()->{'targets'})); |
|---|
| 849 | | # XXX: Delete this, eventually. |
|---|
| 850 | | if ($driverTargetsChanged) { |
|---|
| 851 | | print "Driver targets have changed.\n"; |
|---|
| 852 | | #$Data::Dumper::Terse = 0; |
|---|
| 853 | | #$Data::Dumper::Indent = 1; |
|---|
| 854 | | #print "Current: " . Dumper($data->{$driverName}->{'next'}->{'targets'}) . "\n"; |
|---|
| 855 | | #print "Next: " . Dumper($driver->next()->{'targets'}) . "\n"; |
|---|
| 856 | | } |
|---|
| 857 | | |
|---|
| 858 | | # Copy object data to shared memory. |
|---|
| 859 | | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| 860 | | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| 861 | | $data->{$driverName}->{'status'}->{'is_compromised'} = 0; |
|---|
| 862 | | $data->{$driverName}->{'status'}->{'is_running'} = 1; |
|---|
| 863 | | $data->{$driverName}->{'state'} = $driver; |
|---|
| 864 | | |
|---|
| 865 | | # Release lock on stored driver state. |
|---|
| 866 | | _unlock($data); |
|---|
| 867 | | } |
|---|
| 868 | | |
|---|
| 869 | | # TODO: Perform Integrity Check |
|---|
| 870 | | my $isCompromised = 0; |
|---|
| 871 | | if (defined($integrity)) { |
|---|
| 872 | | # For now, we update a scalar called 'is_compromised' within |
|---|
| 873 | | # the $data->{$driverName}->{'status'} sub-hashtable. |
|---|
| 874 | | print "Performing Integrity Checks...\n"; |
|---|
| 875 | | my $changes = $integrity->check(); |
|---|
| 876 | | if (scalar(@{$changes->{registry}}) || |
|---|
| 877 | | scalar(@{$changes->{filesystem}})) { |
|---|
| 878 | | print "Integrity Check: FAILED\n"; |
|---|
| 879 | | $isCompromised = 1; |
|---|
| 880 | | } else { |
|---|
| 881 | | print "Integrity Check: PASSED\n"; |
|---|
| 882 | | } |
|---|
| 883 | | } |
|---|
| 884 | | # XXX: Check to make sure this doesn't destroy the integrity |
|---|
| 885 | | # object prematurely. |
|---|
| 886 | | # DESTROY this reference, but don't kill any temporary files created. |
|---|
| 887 | | $integrity = undef; |
|---|
| 888 | | |
|---|
| 889 | | # Update driver state one last time, before exiting. |
|---|
| 890 | | |
|---|
| 891 | | # Acquire lock on stored driver state. |
|---|
| 892 | | $data = _lock(); |
|---|
| 893 | | |
|---|
| 894 | | # Check for any additional external driver updates. |
|---|
| 895 | | $driver = _update($driver); |
|---|
| 896 | | |
|---|
| 897 | | # Copy object data to shared memory. |
|---|
| 898 | | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| 899 | | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| 900 | | $data->{$driverName}->{'status'}->{'is_compromised'} = $isCompromised; |
|---|
| 901 | | $data->{$driverName}->{'status'}->{'is_running'} = 0; |
|---|
| 902 | | $data->{$driverName}->{'state'} = $driver; |
|---|
| 903 | | |
|---|
| 904 | | # Thread is about to finish, set the ID back to undef. |
|---|
| 905 | | # XXX: Check to see if this is okay. |
|---|
| 906 | | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| 907 | | |
|---|
| 908 | | # Release lock on stored driver state. |
|---|
| 909 | | _unlock($data); |
|---|
| 910 | | |
|---|
| 911 | | # XXX: Debugging, remove eventually. |
|---|
| 912 | | print "Exiting run() thread.\n"; |
|---|
| 913 | | #print Dumper($driver); |
|---|
| 914 | | # Verbose debugging: |
|---|
| 915 | | #print Dumper($driver->status()); |
|---|
| 916 | | # Short-hand debugging: |
|---|
| 917 | | #my $status = $driver->status(); |
|---|
| 918 | | #print "R(" . $status->{relative_links_remaining} . ") | [ " . |
|---|
| 919 | | # "V(" . $status->{links_remaining} . ") + ". |
|---|
| 920 | | # "P(" . $status->{links_processed} . ") = " . |
|---|
| 921 | | # "T(" . $status->{links_total} . ") ] " . |
|---|
| 922 | | # "| (" . $status->{percent_complete} . ")\n"; |
|---|
| 923 | | }; |
|---|
| 924 | | |
|---|
| 925 | | ################################### |
|---|
| 926 | | ### Driver Cleanup Phase ### |
|---|
| 927 | | ################################### |
|---|
| 928 | | |
|---|
| 929 | | # Check to see if any errors occurred within the thread. |
|---|
| 930 | | # Queue any faults found, to transmit back to the next SOAP |
|---|
| 931 | | # caller. |
|---|
| 932 | | if ($@) { |
|---|
| 933 | | # Release any pending locks, to avoid deadlocks. |
|---|
| 934 | | _unlock(); |
|---|
| 935 | | |
|---|
| 936 | | # Acquire lock on stored driver state. |
|---|
| 937 | | $data = _lock(); |
|---|
| 938 | | |
|---|
| 939 | | # Make sure we update our state to reflect ourself dying. |
|---|
| 940 | | # XXX: Check to see if this is okay. |
|---|
| 941 | | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| 942 | | |
|---|
| 943 | | # Release lock on stored driver state. |
|---|
| 944 | | _unlock($data); |
|---|
| 945 | | |
|---|
| 946 | | # TODO: Do proper fault queuing. |
|---|
| 947 | | print "FAULT: " . $@ . "\n"; |
|---|
| 948 | | } |
|---|
| 949 | | |
|---|
| 950 | | # This threads->detach() call needs to be at the end of the |
|---|
| 951 | | # thread code, because by calling this, we signal that the |
|---|
| 952 | | # child thread is no longer running and thus the |
|---|
| 953 | | # thread->is_running() would return false. |
|---|
| 954 | | #threads->detach(); |
|---|
| 955 | | # XXX: Debugging, remove eventually. |
|---|
| 956 | | print "About to return out of child thread.\n"; |
|---|
| 957 | | #return; |
|---|
| 958 | | }; |
|---|
| | 728 | $thread = threads->create(\&childThread, $driverName); |
|---|
| | 759 | } |
|---|
| | 760 | |
|---|
| | 761 | # TODO: Clean up this comment block. |
|---|
| | 762 | # This function should do the following: |
|---|
| | 763 | # - Initialize all drivers with starting state. |
|---|
| | 764 | # - "Drive" each driver, one-by-one. |
|---|
| | 765 | # - Collect any integrity violations found, with offending |
|---|
| | 766 | # state information. |
|---|
| | 767 | # |
|---|
| | 768 | # Notes: |
|---|
| | 769 | # This function will eventually sit in a sub-thread, allowing the parent |
|---|
| | 770 | # thread to return without any delay. It is expected that the Manager |
|---|
| | 771 | # would then subsequently call a getStatus() operation, in order to |
|---|
| | 772 | # then poll for any new violations found. |
|---|
| | 773 | # |
|---|
| | 774 | # TODO: We need to create a fault reporting mechanism, in order |
|---|
| | 775 | # to properly deal with exceptions/faults that occur within this |
|---|
| | 776 | # thread. |
|---|
| | 777 | sub childThread { |
|---|
| | 778 | |
|---|
| | 779 | # Extract arguments. |
|---|
| | 780 | my $driverName = shift; |
|---|
| | 781 | |
|---|
| | 782 | # XXX: Check if we need this. |
|---|
| | 783 | # threads->yield(); |
|---|
| | 784 | |
|---|
| | 785 | # Trap all faults that may occur from these asynchronous operations. |
|---|
| | 786 | eval { |
|---|
| | 787 | |
|---|
| | 788 | ################################### |
|---|
| | 789 | ### Driver Initialization Phase ### |
|---|
| | 790 | ################################### |
|---|
| | 791 | |
|---|
| | 792 | # Initially set local integrity object to undef. |
|---|
| | 793 | my $integrity = undef; |
|---|
| | 794 | |
|---|
| | 795 | # Initially set all driver objects to undef. |
|---|
| | 796 | my $driver = undef; |
|---|
| | 797 | |
|---|
| | 798 | # Acquire lock on stored driver state. |
|---|
| | 799 | $data = _lock(); |
|---|
| | 800 | |
|---|
| | 801 | if ($PERFORM_INTEGRITY_CHECKS) { |
|---|
| | 802 | # XXX: WARNING - The $integrityState object data is NOT thread-safe |
|---|
| | 803 | # (since it relies on external data stored on the file system). |
|---|
| | 804 | # As such, do NOT try to call integrity checks on multiple, simultaneous |
|---|
| | 805 | # asynchronous threaded drivers. |
|---|
| | 806 | $integrity = thaw($integrityState); |
|---|
| | 807 | # Perform initial integrity baseline check. |
|---|
| | 808 | #print "Initializing Integrity Check...\n"; |
|---|
| | 809 | # TODO: Initialize Integrity Checks |
|---|
| | 810 | #$integrity = HoneyClient::Agent::Integrity->new(); |
|---|
| | 811 | } |
|---|
| | 812 | |
|---|
| | 813 | # Now, initialize each driver object. |
|---|
| | 814 | # Figure out which $driver object to use... |
|---|
| | 815 | my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; |
|---|
| | 816 | |
|---|
| | 817 | if (!defined($data->{$driverName}->{'state'})) { |
|---|
| | 818 | |
|---|
| | 819 | # If the driver state is undefined, then |
|---|
| | 820 | # create a new state object. |
|---|
| | 821 | $driver = $driverClass->new(); |
|---|
| | 822 | |
|---|
| | 823 | } else { |
|---|
| | 824 | # Then the driver state object is already defined, |
|---|
| | 825 | # so go ahead and reuse it. |
|---|
| | 826 | $driver = $driverClass->new( |
|---|
| | 827 | %{$data->{$driverName}->{'state'}}, |
|---|
| | 828 | ); |
|---|
| | 829 | } |
|---|
| | 830 | |
|---|
| | 831 | # Next, we make sure we have no updates, before we update |
|---|
| | 832 | # the corresponding shared memory version. |
|---|
| | 833 | $driver = _update($driver); |
|---|
| | 834 | |
|---|
| | 835 | # Once we've initialized the object, be sure to update |
|---|
| | 836 | # the corresponding shared memory version. We do this |
|---|
| | 837 | # one time before the loop starts, in case we end up |
|---|
| | 838 | # finishing before we drove anywhere. |
|---|
| | 839 | |
|---|
| | 840 | # Copy object data to shared memory. |
|---|
| | 841 | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| | 842 | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| | 843 | $data->{$driverName}->{'status'}->{'is_compromised'} = 0; |
|---|
| | 844 | $data->{$driverName}->{'status'}->{'is_running'} = 1; |
|---|
| | 845 | $data->{$driverName}->{'state'} = $driver; |
|---|
| | 846 | |
|---|
| | 847 | # XXX: Check to see if this is okay. |
|---|
| | 848 | # if ($driver->isFinished()) { |
|---|
| | 849 | # # Thread is about to finish, set the ID back to undef. |
|---|
| | 850 | # # This looks ugly, but setting it this early avoids the |
|---|
| | 851 | # # potential race condition of when the run() thread is finished |
|---|
| | 852 | # # and when updateState() checks for $driverData->{$driverName}->{'thread_id'} |
|---|
| | 853 | # # to be set to undef. |
|---|
| | 854 | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| | 855 | # } |
|---|
| | 856 | |
|---|
| | 857 | # Release lock on stored driver state. |
|---|
| | 858 | _unlock($data); |
|---|
| | 859 | |
|---|
| | 860 | ################################### |
|---|
| | 861 | ### Driver Running Phase ### |
|---|
| | 862 | ################################### |
|---|
| | 863 | |
|---|
| | 864 | # Boolean to indicate that the driver is about to transition |
|---|
| | 865 | # to a new set of targets upon the next drive() operation. |
|---|
| | 866 | my $driverTargetsChanged = 0; |
|---|
| | 867 | |
|---|
| | 868 | while (!$driver->isFinished() && !$driverTargetsChanged) { |
|---|
| | 869 | # XXX: Debug. Remove this. |
|---|
| | 870 | # We assume $driver->next() returns defined data. |
|---|
| | 871 | foreach my $resource (keys %{$driver->next()->{resources}}) { |
|---|
| | 872 | print "Using Resource: " . $resource . "\n"; |
|---|
| | 873 | } |
|---|
| | 874 | |
|---|
| | 875 | # Drive the driver for one step. |
|---|
| | 876 | # If the operation fails, then an exception will be generated. |
|---|
| | 877 | $driver->drive(); |
|---|
| | 878 | |
|---|
| | 879 | # Acquire lock on stored driver state. |
|---|
| | 880 | $data = _lock(); |
|---|
| | 881 | |
|---|
| | 882 | # Check for any additional external driver updates. |
|---|
| | 883 | $driver = _update($driver); |
|---|
| | 884 | |
|---|
| | 885 | # Check to see if our driver's targets have changed. |
|---|
| | 886 | $driverTargetsChanged = not(Compare($data->{$driverName}->{'next'}->{'targets'}, $driver->next()->{'targets'})); |
|---|
| | 887 | # XXX: Delete this, eventually. |
|---|
| | 888 | if ($driverTargetsChanged) { |
|---|
| | 889 | print "Driver targets have changed.\n"; |
|---|
| | 890 | #$Data::Dumper::Terse = 0; |
|---|
| | 891 | #$Data::Dumper::Indent = 1; |
|---|
| | 892 | #print "Current: " . Dumper($data->{$driverName}->{'next'}->{'targets'}) . "\n"; |
|---|
| | 893 | #print "Next: " . Dumper($driver->next()->{'targets'}) . "\n"; |
|---|
| | 894 | } |
|---|
| | 895 | |
|---|
| | 896 | # Copy object data to shared memory. |
|---|
| | 897 | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| | 898 | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| | 899 | $data->{$driverName}->{'status'}->{'is_compromised'} = 0; |
|---|
| | 900 | $data->{$driverName}->{'status'}->{'is_running'} = 1; |
|---|
| | 901 | $data->{$driverName}->{'state'} = $driver; |
|---|
| | 902 | |
|---|
| | 903 | # Release lock on stored driver state. |
|---|
| | 904 | _unlock($data); |
|---|
| | 905 | } |
|---|
| | 906 | |
|---|
| | 907 | # TODO: Perform Integrity Check |
|---|
| | 908 | my $isCompromised = 0; |
|---|
| | 909 | if (defined($integrity)) { |
|---|
| | 910 | # For now, we update a scalar called 'is_compromised' within |
|---|
| | 911 | # the $data->{$driverName}->{'status'} sub-hashtable. |
|---|
| | 912 | print "Performing Integrity Checks...\n"; |
|---|
| | 913 | my $changes = $integrity->check(); |
|---|
| | 914 | if (scalar(@{$changes->{registry}}) || |
|---|
| | 915 | scalar(@{$changes->{filesystem}})) { |
|---|
| | 916 | print "Integrity Check: FAILED\n"; |
|---|
| | 917 | $isCompromised = 1; |
|---|
| | 918 | } else { |
|---|
| | 919 | print "Integrity Check: PASSED\n"; |
|---|
| | 920 | } |
|---|
| | 921 | } |
|---|
| | 922 | # XXX: Check to make sure this doesn't destroy the integrity |
|---|
| | 923 | # object prematurely. |
|---|
| | 924 | # DESTROY this reference, but don't kill any temporary files created. |
|---|
| | 925 | $integrity = undef; |
|---|
| | 926 | |
|---|
| | 927 | # Update driver state one last time, before exiting. |
|---|
| | 928 | |
|---|
| | 929 | # Acquire lock on stored driver state. |
|---|
| | 930 | $data = _lock(); |
|---|
| | 931 | |
|---|
| | 932 | # Check for any additional external driver updates. |
|---|
| | 933 | $driver = _update($driver); |
|---|
| | 934 | |
|---|
| | 935 | # Copy object data to shared memory. |
|---|
| | 936 | $data->{$driverName}->{'next'} = $driver->next(); |
|---|
| | 937 | $data->{$driverName}->{'status'} = $driver->status(); |
|---|
| | 938 | $data->{$driverName}->{'status'}->{'is_compromised'} = $isCompromised; |
|---|
| | 939 | $data->{$driverName}->{'status'}->{'is_running'} = 0; |
|---|
| | 940 | $data->{$driverName}->{'state'} = $driver; |
|---|
| | 941 | |
|---|
| | 942 | # Thread is about to finish, set the ID back to undef. |
|---|
| | 943 | # XXX: Check to see if this is okay. |
|---|
| | 944 | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| | 945 | |
|---|
| | 946 | # Release lock on stored driver state. |
|---|
| | 947 | _unlock($data); |
|---|
| | 948 | |
|---|
| | 949 | # XXX: Debugging, remove eventually. |
|---|
| | 950 | print "Exiting run() thread.\n"; |
|---|
| | 951 | #print Dumper($driver); |
|---|
| | 952 | # Verbose debugging: |
|---|
| | 953 | #print Dumper($driver->status()); |
|---|
| | 954 | # Short-hand debugging: |
|---|
| | 955 | #my $status = $driver->status(); |
|---|
| | 956 | #print "R(" . $status->{relative_links_remaining} . ") | [ " . |
|---|
| | 957 | # "V(" . $status->{links_remaining} . ") + ". |
|---|
| | 958 | # "P(" . $status->{links_processed} . ") = " . |
|---|
| | 959 | # "T(" . $status->{links_total} . ") ] " . |
|---|
| | 960 | # "| (" . $status->{percent_complete} . ")\n"; |
|---|
| | 961 | }; |
|---|
| | 962 | |
|---|
| | 963 | ################################### |
|---|
| | 964 | ### Driver Cleanup Phase ### |
|---|
| | 965 | ################################### |
|---|
| | 966 | |
|---|
| | 967 | # Check to see if any errors occurred within the thread. |
|---|
| | 968 | # Queue any faults found, to transmit back to the next SOAP |
|---|
| | 969 | # caller. |
|---|
| | 970 | if ($@) { |
|---|
| | 971 | # Release any pending locks, to avoid deadlocks. |
|---|
| | 972 | _unlock(); |
|---|
| | 973 | |
|---|
| | 974 | # Acquire lock on stored driver state. |
|---|
| | 975 | $data = _lock(); |
|---|
| | 976 | |
|---|
| | 977 | # Make sure we update our state to reflect ourself dying. |
|---|
| | 978 | # XXX: Check to see if this is okay. |
|---|
| | 979 | # $data->{$driverName}->{'thread_id'} = undef; |
|---|
| | 980 | |
|---|
| | 981 | # Release lock on stored driver state. |
|---|
| | 982 | _unlock($data); |
|---|
| | 983 | |
|---|
| | 984 | # TODO: Do proper fault queuing. |
|---|
| | 985 | print "FAULT: " . $@ . "\n"; |
|---|
| | 986 | } |
|---|
| | 987 | |
|---|
| | 988 | # This threads->detach() call needs to be at the end of the |
|---|
| | 989 | # thread code, because by calling this, we signal that the |
|---|
| | 990 | # child thread is no longer running and thus the |
|---|
| | 991 | # thread->is_running() would return false. |
|---|
| | 992 | #threads->detach(); |
|---|
| | 993 | # XXX: Debugging, remove eventually. |
|---|
| | 994 | print "About to return out of child thread.\n"; |
|---|
| | 995 | #return; |
|---|