Skip to content

Commit d53fdd8

Browse files
committed
Revert "feat(fsm): add support to announce Windows processes."
This reverts commit 1da36f4. Signed-off-by: Paulo Vital <[email protected]>
1 parent 3c6edd1 commit d53fdd8

File tree

1 file changed

+44
-97
lines changed

1 file changed

+44
-97
lines changed

src/instana/fsm.py

Lines changed: 44 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
import subprocess
99
import sys
1010
import threading
11-
from typing import TYPE_CHECKING, Any, Callable, List
11+
from typing import TYPE_CHECKING, Any, Callable
1212

1313
from fysom import Fysom
1414

1515
from instana.log import logger
1616
from instana.util import get_default_gateway
1717
from instana.util.process_discovery import Discovery
18-
from instana.util.runtime import is_windows
1918
from instana.version import VERSION
2019

2120
if TYPE_CHECKING:
@@ -104,16 +103,48 @@ def lookup_agent_host(self, e: Any) -> bool:
104103
return False
105104

106105
def announce_sensor(self, e: Any) -> bool:
107-
pid: int = os.getpid()
108106
logger.debug(
109-
f"Attempting to announce PID {pid} to the agent on {self.agent.options.agent_host}:{self.agent.options.agent_port}"
107+
f"Attempting to make an announcement to the agent on {self.agent.options.agent_host}:{self.agent.options.agent_port}"
110108
)
109+
pid = os.getpid()
111110

112-
cmdline = self._get_cmdline(pid)
111+
try:
112+
if os.path.isfile("/proc/self/cmdline"):
113+
with open("/proc/self/cmdline") as cmd:
114+
cmdinfo = cmd.read()
115+
cmdline = cmdinfo.split("\x00")
116+
else:
117+
# Python doesn't provide a reliable method to determine what
118+
# the OS process command line may be. Here we are forced to
119+
# rely on ps rather than adding a dependency on something like
120+
# psutil which requires dev packages, gcc etc...
121+
proc = subprocess.Popen(
122+
["ps", "-p", str(pid), "-o", "command"], stdout=subprocess.PIPE
123+
)
124+
(out, _) = proc.communicate()
125+
parts = out.split(b"\n")
126+
cmdline = [parts[1].decode("utf-8")]
127+
except Exception:
128+
cmdline = sys.argv
129+
logger.debug("announce_sensor", exc_info=True)
113130

114131
d = Discovery(pid=self.__get_real_pid(), name=cmdline[0], args=cmdline[1:])
115132

116-
self._setup_socket_connection(d, pid)
133+
# If we're on a system with a procfs
134+
if os.path.exists("/proc/"):
135+
try:
136+
# In CentOS 7, some odd things can happen such as:
137+
# PermissionError: [Errno 13] Permission denied: '/proc/6/fd/8'
138+
# Use a try/except as a safety
139+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
140+
sock.connect(
141+
(self.agent.options.agent_host, self.agent.options.agent_port)
142+
)
143+
path = f"/proc/{pid}/fd/{sock.fileno()}"
144+
d.fd = sock.fileno()
145+
d.inode = os.readlink(path)
146+
except: # noqa: E722
147+
logger.debug("Error generating file descriptor: ", exc_info=True)
117148

118149
payload = self.agent.announce(d)
119150

@@ -158,112 +189,28 @@ def on_good2go(self, _: Any) -> None:
158189
def __get_real_pid(self) -> int:
159190
"""
160191
Attempts to determine the true process ID by querying the
161-
/proc/<pid>/sched file on Linux systems or using the OS default PID.
162-
For Windows, we use the standard OS PID as there's no equivalent concept
163-
of container PIDs vs host PIDs.
192+
/proc/<pid>/sched file. This works on systems with a proc filesystem.
193+
Otherwise default to os default.
164194
"""
165195
pid = None
166196

167-
# For Linux systems with procfs
168197
if os.path.exists("/proc/"):
169198
sched_file = f"/proc/{os.getpid()}/sched"
170199

171200
if os.path.isfile(sched_file):
172201
try:
173-
with open(sched_file) as file:
174-
line = file.readline()
175-
g = re.search(r"\((\d+),", line)
176-
if g and len(g.groups()) == 1:
177-
pid = int(g.groups()[0])
202+
file = open(sched_file)
203+
line = file.readline()
204+
g = re.search(r"\((\d+),", line)
205+
if g and len(g.groups()) == 1:
206+
pid = int(g.groups()[0])
178207
except Exception:
179208
logger.debug("parsing sched file failed", exc_info=True)
180209

181-
# For Windows or if Linux method failed
182210
if pid is None:
183211
pid = os.getpid()
184212

185213
return pid
186214

187-
def _get_cmdline_windows(self) -> List[str]:
188-
"""
189-
Get command line using Windows API
190-
"""
191-
import ctypes
192-
from ctypes import wintypes
193-
194-
GetCommandLineW = ctypes.windll.kernel32.GetCommandLineW
195-
GetCommandLineW.argtypes = []
196-
GetCommandLineW.restype = wintypes.LPCWSTR
197-
198-
cmd = GetCommandLineW()
199-
# Simple parsing - this is a basic approach and might need refinement
200-
# for complex command lines with quotes and spaces
201-
return cmd.split()
202-
203-
def _get_cmdline_linux_proc(self) -> List[str]:
204-
"""
205-
Get command line from Linux /proc filesystem
206-
"""
207-
with open("/proc/self/cmdline") as cmd:
208-
cmdinfo = cmd.read()
209-
return cmdinfo.split("\x00")
210-
211-
def _get_cmdline_unix_ps(self, pid: int) -> List[str]:
212-
"""
213-
Get command line using ps command (for Unix-like systems without /proc)
214-
"""
215-
proc = subprocess.Popen(
216-
["ps", "-p", str(pid), "-o", "command"], stdout=subprocess.PIPE
217-
)
218-
(out, _) = proc.communicate()
219-
parts = out.split(b"\n")
220-
return [parts[1].decode("utf-8")]
221-
222-
def _get_cmdline_unix(self, pid: int) -> List[str]:
223-
"""
224-
Get command line using Unix
225-
"""
226-
if os.path.isfile("/proc/self/cmdline"):
227-
return self._get_cmdline_linux_proc()
228-
else:
229-
return self._get_cmdline_unix_ps(pid)
230-
231-
def _get_cmdline(self, pid: int) -> List[str]:
232-
"""
233-
Get command line in a platform-independent way
234-
"""
235-
try:
236-
if is_windows():
237-
return self._get_cmdline_windows()
238-
else:
239-
return self._get_cmdline_unix(pid)
240-
except Exception:
241-
logger.debug("Error getting command line", exc_info=True)
242-
return sys.argv
243-
244-
def _setup_socket_connection(self, discovery: Discovery, pid: int) -> None:
245-
"""
246-
Set up socket connection and populate discovery object with socket details
247-
"""
248-
try:
249-
# In CentOS 7, some odd things can happen such as:
250-
# PermissionError: [Errno 13] Permission denied: '/proc/6/fd/8'
251-
# Use a try/except as a safety
252-
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
253-
sock.connect((self.agent.options.agent_host, self.agent.options.agent_port))
254-
discovery.fd = sock.fileno()
255-
256-
# If we're on a system with a procfs (Linux)
257-
if os.path.exists("/proc/"):
258-
try:
259-
path = "/proc/%d/fd/%d" % (pid, sock.fileno())
260-
discovery.inode = os.readlink(path)
261-
except Exception:
262-
logger.debug(
263-
"Error generating file descriptor inode: ", exc_info=True
264-
)
265-
except Exception:
266-
logger.debug("Error creating socket connection: ", exc_info=True)
267-
268215

269216
# Made with Bob

0 commit comments

Comments
 (0)