Replace MonitorProcess thread with CheckProcess timer like we did in MSC.app

This commit is contained in:
Greg Neagle
2014-02-26 14:01:31 -08:00
parent 807af76db5
commit cca26f6751
5 changed files with 44 additions and 110 deletions
@@ -74,6 +74,7 @@ class MSUStatusWindowController(NSObject):
restartAlertDismissed = 0
got_status_update = False
receiving_notifications = False
timer = None
@IBAction
def stopBtnClicked_(self, sender):
@@ -109,10 +110,6 @@ class MSUStatusWindowController(NSObject):
None,
NSNotificationSuspensionBehaviorDeliverImmediately)
self.receiving_notifications = True
# start our process monitor thread so we can be notified about
# process failure
NSThread.detachNewThreadSelector_toTarget_withObject_(
self.monitorProcess, self, None)
def unregisterForNotifications(self):
'''Tell the DistributedNotificationCenter to stop sending us notifications'''
@@ -157,8 +154,14 @@ class MSUStatusWindowController(NSObject):
self.progressIndicator.startAnimation_(self)
self.window.orderFrontRegardless()
self.registerForNotifications()
# start our process monitor timer so we can be notified about
# process failure
self.timeout_counter = 6
self.saw_process = False
self.timer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(
5.0, self, self.checkProcess_, None, YES)
def monitorProcess(self):
def checkProcess_(self, timer):
'''Monitors managedsoftwareupdate process for failure to start
or unexpected exit, so we're not waiting around forever if
managedsoftwareupdate isn't running.'''
@@ -166,38 +169,27 @@ class MSUStatusWindowController(NSObject):
NEVER_STARTED = -2
UNEXPECTEDLY_QUIT = -1
timeout_counter = 6
saw_process = False
NSLog('checkProcess timer fired')
# Autorelease pool for memory management
pool = NSAutoreleasePool.alloc().init()
while self.receiving_notifications:
if self.got_status_update:
# we got a status update since we last checked; no need to
# check the process table
timeout_counter = 6
saw_process = True
# clear the flag so we have to get another status update
self.got_status_update = False
elif munki.pythonScriptRunning(PYTHON_SCRIPT_NAME):
timeout_counter = 6
saw_process = True
if self.got_status_update:
# we got a status update since we last checked; no need to
# check the process table
self.timeout_counter = 6
self.saw_process = True
# clear the flag so we have to get another status update
self.got_status_update = False
elif munki.pythonScriptRunning(PYTHON_SCRIPT_NAME):
self.timeout_counter = 6
self.saw_process = True
else:
NSLog('managedsoftwareupdate not running...')
self.timeout_counter -= 1
if self.timeout_counter == 0:
NSLog('Timed out waiting for managedsoftwareupdate.')
if self.saw_process:
self.statusSessionFailed_(UNEXPECTEDLY_QUIT)
else:
NSLog('No managedsoftwareupdate running...')
timeout_counter -= 1
if timeout_counter == 0:
NSLog('Timed out waiting for managedsoftwareupdate.')
if saw_process:
sessionResult = UNEXPECTEDLY_QUIT
else:
sessionResult = NEVER_STARTED
break
time.sleep(5)
if self.receiving_notifications:
self.performSelectorOnMainThread_withObject_waitUntilDone_(
self.statusSessionFailed_, sessionResult, NO)
# Clean up autorelease pool
del pool
self.statusSessionFailed_(NEVER_STARTED)
def statusSessionFailed_(self, sessionResult):
NSLog('statusSessionFailed: %s' % sessionResult)
@@ -209,7 +201,11 @@ class MSUStatusWindowController(NSObject):
if self.backdropWindow and self.backdropWindow.isVisible():
self.backdropWindow.orderOut_(self)
self.window.orderOut_(self)
# clean up timer
if self.timer:
self.timer.invalidate()
self.timer = None
def displayBackdropWindow(self):
if self.backdropWindow:
self.backdropWindow.setCanBecomeVisibleWithoutLogin_(True)
@@ -1,5 +1,5 @@
//
// Prefix header for all source files of the 'Managed Software Update' target in the 'Managed Software Update' project
// Prefix header for all source files of the 'MunkiStatus' target in the 'MunkiStatus' project
//
#ifdef __OBJC__
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment version="1060" defaultVersion="1060" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
@@ -14,10 +14,10 @@
</customObject>
<menu title="AMainMenu" systemMenu="main" id="29" userLabel="MainMenu">
<items>
<menuItem title="Managed Software Update" id="56">
<menu key="submenu" title="Managed Software Update" systemMenu="apple" id="57">
<menuItem title="MunkiStatus" id="56">
<menu key="submenu" title="MunkiStatus" systemMenu="apple" id="57">
<items>
<menuItem title="About Managed Software Update" id="58">
<menuItem title="About MunkiStatus" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
@@ -32,7 +32,7 @@
<menuItem isSeparatorItem="YES" id="144">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide Managed Software Update" keyEquivalent="h" id="134">
<menuItem title="Hide MunkiStatus" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
@@ -51,7 +51,7 @@
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit Managed Software Update" keyEquivalent="q" id="136" userLabel="1111">
<menuItem title="Quit MunkiStatus" keyEquivalent="q" id="136" userLabel="1111">
<connections>
<action selector="terminate:" target="-1" id="369"/>
</connections>
@@ -128,7 +128,7 @@
<menuItem title="Help" id="103" userLabel="1">
<menu key="submenu" title="Help" id="106" userLabel="2">
<items>
<menuItem title="Managed Software Update Help" keyEquivalent="?" id="111">
<menuItem title="MunkiStatus Help" keyEquivalent="?" id="111">
<connections>
<action selector="showHelp:" target="-1" id="360"/>
</connections>
+1 -1
View File
@@ -1,6 +1,6 @@
#
# main.py
# Managed Software Update
# MunkiStatus
#
# Copyright 2013-2014 Greg Neagle.
#
+3 -65
View File
@@ -1,7 +1,7 @@
# encoding: utf-8
#
# munki.py
# Managed Software Update
# MunkiStatus
#
# Created by Greg Neagle on 2/11/10.
# Copyright 2010-2014 Greg Neagle.
@@ -18,7 +18,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
'''munki-specific code for use with Managed Software Update'''
'''munki-specific code for use with MunkiStatus'''
import os
import stat
@@ -103,66 +103,4 @@ def pythonScriptRunning(scriptname):
pass
# if we get here we didn't find a Python script with scriptname
# (other than ourselves)
return 0
def getPowerInfo():
'''Returns power info in a dictionary'''
power_dict = {}
power_dict['PowerSource'] = 'Unknown Power'
power_dict['BatteryCharge'] = -1
power_dict['ChargingStatus'] = 'unknown'
power_dict['TimeRemaining'] = -1
cmd = ['/usr/bin/pmset', '-g', 'ps']
proc = subprocess.Popen(cmd, bufsize=-1, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(output, unused_error) = proc.communicate()
if proc.returncode:
# handle error
return power_dict
#
# output from `pmset -g ps` looks like:
#
# Currently drawing from 'AC Power'
# -InternalBattery-0 100%; charged; 0:00 remaining
#
# or
#
# Currently drawing from 'AC Power'
# -InternalBattery-0 98%; charging; 0:08 remaining
#
# or
#
# Currently drawing from 'Battery Power'
# -InternalBattery-0 100%; discharging; (no estimate)
#
# or
#
# Currently drawing from 'Battery Power'
# -InternalBattery-0 100%; discharging; 5:55 remaining
#
line = output.splitlines()
if 'AC Power' in line[0]:
power_dict['PowerSource'] = 'AC Power'
power_dict['ChargingStatus'] = 'not applicable'
if 'Battery Power' in line[0]:
power_dict['PowerSource'] = 'Battery Power'
if len(line) > 1:
part = line[1].split()
try:
power_dict['BatteryCharge'] = int(part[1].rstrip('%;'))
except (IndexError, ValueError):
pass
try:
power_dict['ChargingStatus'] = part[2].rstrip(';')
except IndexError:
pass
try:
time_remaining_text = part[3]
time_part = time_remaining_text.split(':')
minutes = 60 * int(time_part[0]) + int(time_part[1])
power_dict['TimeRemaining'] = minutes
except (IndexError, ValueError):
pass
return power_dict
return 0