Skip to content

fix: re-entrant Collector threads on musl-based systems. #737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 22 additions & 33 deletions src/instana/collector/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

import queue # pylint: disable=import-error
import threading
import time

from instana.log import logger
from instana.util import DictionaryOfStan, every
from instana.util import DictionaryOfStan


class BaseCollector(object):
Expand Down Expand Up @@ -76,22 +77,22 @@ def start(self):
"""
if self.is_reporting_thread_running():
if self.thread_shutdown.is_set():
# Shutdown still in progress; Reschedule this start in 5 seconds from now
# Force a restart.
self.thread_shutdown.clear()
# Reschedule this start in 5 seconds from now
timer = threading.Timer(5, self.start)
timer.daemon = True
timer.name = "Collector Timed Start"
timer.start()
return
logger.debug(
"BaseCollector.start non-fatal: call but thread already running (started: %s)",
self.started,
f"BaseCollector.start non-fatal: call but thread already running (started: {self.started})"
)
return

if self.agent.can_send():
logger.debug("BaseCollector.start: launching collection thread")
self.thread_shutdown.clear()
self.reporting_thread = threading.Thread(target=self.thread_loop, args=())
self.reporting_thread = threading.Thread(target=self.background_report, args=())
self.reporting_thread.daemon = True
self.reporting_thread.name = self.THREAD_NAME
self.reporting_thread.start()
Expand All @@ -113,37 +114,25 @@ def shutdown(self, report_final=True):
self.prepare_and_report_data()
self.started = False

def thread_loop(self):
"""
Just a loop that is run in the background thread.
@return: None
"""
every(
self.report_interval,
self.background_report,
"Instana Collector: prepare_and_report_data",
)

def background_report(self):
def background_report(self) -> None:
"""
The main work-horse method to report data in the background thread.
@return: Boolean
"""
if self.thread_shutdown.is_set():
logger.debug(
"Thread shutdown signal is active: Shutting down reporting thread"
)
return False

self.prepare_and_report_data()

if self.thread_shutdown.is_set():
logger.debug(
"Thread shutdown signal is active: Shutting down reporting thread"
)
return False
This method runs indefinitely, preparing and reporting data at regular
intervals.
It checks for a shutdown signal and stops execution if it's set.

@return: None
"""
while True:
if self.thread_shutdown.is_set():
logger.debug(
"Thread shutdown signal is active: Shutting down reporting thread"
)
break

return True
self.prepare_and_report_data()
time.sleep(self.report_interval)

def prepare_and_report_data(self):
"""
Expand Down
30 changes: 2 additions & 28 deletions src/instana/util/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# (c) Copyright IBM Corp. 2021
# (c) Copyright Instana Inc. 2020

import importlib.metadata
import json
import time
from collections import defaultdict
from urllib import parse

import importlib.metadata

from ..log import logger
from instana.log import logger


def nested_dictionary():
Expand Down Expand Up @@ -111,30 +109,6 @@ def get_default_gateway():
logger.warning("get_default_gateway: ", exc_info=True)


def every(delay, task, name):
"""
Executes a task every `delay` seconds

:param delay: the delay in seconds
:param task: the method to run. The method should return False if you want the loop to stop.
:return: None
"""
next_time = time.time() + delay

while True:
time.sleep(max(0, next_time - time.time()))
try:
if task() is False:
break
except Exception:
logger.debug(
"Problem while executing repetitive task: %s", name, exc_info=True
)

# skip tasks if we are behind schedule:
next_time += (time.time() - next_time) // delay * delay + delay


def validate_url(url):
"""
Validate if <url> is a valid url
Expand Down
2 changes: 1 addition & 1 deletion src/instana/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

# Module version file. Used by setup.py and snapshot reporting.

VERSION = "3.4.0"
VERSION = "3.4.0+dev.celero.debug.10"
Loading