Skip to content

Commit 8536ff5

Browse files
author
Teddy Reed
authored
extensions: Add watchdog thread and open retries (#31)
1 parent 7304d61 commit 8536ff5

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

osquery/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66
__title__ = "osquery"
7-
__version__ = "1.8.0"
7+
__version__ = "2.2.0"
88
__author__ = "osquery developers"
99
__license__ = "BSD"
1010
__copyright__ = "Copyright 2015 Facebook"

osquery/extension_client.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from __future__ import print_function
99
from __future__ import unicode_literals
1010

11+
import time
12+
1113
from thrift.protocol import TBinaryProtocol
1214
from thrift.transport import TSocket
1315
from thrift.transport import TTransport
@@ -41,9 +43,18 @@ def close(self):
4143
if self._transport:
4244
self._transport.close()
4345

44-
def open(self):
46+
def open(self, timeout=1, interval=0.2):
4547
"""Attempt to open the UNIX domain socket"""
46-
self._transport.open()
48+
delay = 0
49+
while delay < timeout:
50+
try:
51+
self._transport.open()
52+
return True
53+
except TTransport.TTransportException:
54+
pass
55+
delay += interval
56+
time.sleep(interval)
57+
return False
4758

4859
def extension_manager_client(self):
4960
"""Return an extension manager (osquery core) client."""

osquery/extension_manager.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@
88
from __future__ import print_function
99
from __future__ import unicode_literals
1010

11-
import sys
11+
import os
12+
import threading
13+
import time
1214

1315
from osquery.extensions.Extension import Iface
1416
from osquery.extensions.ttypes import ExtensionResponse, ExtensionStatus
1517
from osquery.singleton import Singleton
1618

19+
def shutdown_request(code, timeout=1):
20+
"""A delayed shutdown request."""
21+
time.sleep(timeout)
22+
os._exit(code)
23+
1724
class ExtensionManager(Singleton, Iface):
1825
"""The thrift server for handling extension requests
1926
@@ -64,7 +71,10 @@ def add_plugin(self, plugin):
6471

6572
def shutdown(self):
6673
"""The osquery extension manager requested a shutdown"""
67-
sys.exit(0)
74+
rt = threading.Thread(target=shutdown_request, args=(0,))
75+
rt.daemon = True
76+
rt.start()
77+
return ExtensionStatus(code=0, message="OK")
6878

6979
def registry(self):
7080
"""Accessor for the internal _registry member variable"""

osquery/management.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
from __future__ import unicode_literals
1010

1111
import argparse
12+
import os
1213
import shutil
1314
import socket
1415
import subprocess
1516
import sys
1617
import tempfile
18+
import threading
1719
import time
1820

1921
from thrift.protocol import TBinaryProtocol
@@ -144,6 +146,19 @@ def parse_cli_params():
144146
help="Enable verbose informational messages")
145147
return parser.parse_args()
146148

149+
def start_watcher(client, interval):
150+
"""Ping the osquery extension manager to detect dirty shutdowns."""
151+
try:
152+
while True:
153+
status = client.extension_manager_client().ping()
154+
if status.code is not 0:
155+
break
156+
time.sleep(interval)
157+
except socket.error:
158+
# The socket was torn down.
159+
pass
160+
os._exit(0)
161+
147162
def start_extension(name="<unknown>", version="0.0.0", sdk_version="1.8.0",
148163
min_sdk_version="1.8.0"):
149164
"""Start your extension by communicating with osquery core and starting
@@ -157,7 +172,8 @@ def start_extension(name="<unknown>", version="0.0.0", sdk_version="1.8.0",
157172
"""
158173
args = parse_cli_params()
159174
client = ExtensionClient(path=args.socket)
160-
client.open()
175+
if not client.open(args.timeout):
176+
return
161177
ext_manager = ExtensionManager()
162178

163179
# try connecting to the desired osquery core extension manager socket
@@ -184,6 +200,11 @@ def start_extension(name="<unknown>", version="0.0.0", sdk_version="1.8.0",
184200
message=status.message,
185201
)
186202

203+
# Start a watchdog thread to monitor the osquery process.
204+
rt = threading.Thread(target=start_watcher, args=(client, args.interval))
205+
rt.daemon = True
206+
rt.start()
207+
187208
# start a thrift server listening at the path dictated by the uuid returned
188209
# by the osquery core extension manager
189210
ext_manager.uuid = status.uuid

0 commit comments

Comments
 (0)