| Server IP : 85.112.90.236 / Your IP : 192.168.1.26 Web Server : Apache System : Linux 85-112-90-236.cprapid.com 6.12.0-211.7.3.el10_2.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 19 12:46:58 EDT 2026 x86_64 User : ftechme ( 1002) PHP Version : 8.2.32 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /lib64/tracker-3.0/trackertestutils/ |
Upload File : |
# Copyright (C) 2010, Nokia <jean-luc.lamadon@nokia.com>
# Copyright (C) 2019, Sam Thursfield <sam@afuera.me.uk>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
"""
Sandbox environment for running tests.
The sandbox is essentially a private D-Bus daemon.
"""
from gi.repository import Gio
import atexit
import logging
import os
import signal
import subprocess
from . import dbusdaemon
from .dconf import DConfClient, TemporaryDConfProfile
from . import psutil_mini as psutil
log = logging.getLogger(__name__)
TRACKER_DBUS_PREFIX = 'org.freedesktop.Tracker3'
TRACKER_MINER_FS_BUSNAME = 'org.freedesktop.Tracker3.Miner.Files'
_process_list = []
def _cleanup_processes():
for process in _process_list:
log.debug("helpers._cleanup_processes: stopping %s", process)
process.stop()
atexit.register(_cleanup_processes)
class TrackerSandbox:
"""
Run Tracker daemons isolated from the real user session.
The primary method of sandboxing is running one or more private D-Bus
daemons, which take place of the host's session and system bus.
"""
def __init__(self, session_bus_config_file, system_bus_config_file=None,
extra_env=None):
self.extra_env = extra_env or {}
self.session_bus = dbusdaemon.DBusDaemon(
name='sandbox-session-bus', config_file=session_bus_config_file)
if system_bus_config_file:
self.system_bus = dbusdaemon.DBusDaemon(
name='sandbox-system-bus', config_file=system_bus_config_file)
else:
self.system_bus = None
self._dconf_profile = TemporaryDConfProfile()
def get_environment(self):
env = os.environ
env.update(self.extra_env)
env['G_MESSAGES_PREFIXED'] = 'all'
# This avoids an issue where gvfsd-fuse can start up while the bus is
# shutting down. If it fails to connect to the bus, it continues to
# run anyway which leads to our dbus-daemon failing to shut down.
#
# Since https://gitlab.gnome.org/GNOME/gvfs/issues/323 was implemented
# in GVFS 1.42 this problem may have gone away.
env['GVFS_DISABLE_FUSE'] = '1'
# Precreate runtime dir, to avoid this warning from dbus-daemon:
#
# Unable to set up transient service directory: XDG_RUNTIME_DIR "/home/sam/tracker-tests/tmp_59i3ev1/run" not available: No such file or directory
#
xdg_runtime_dir = env.get('XDG_RUNTIME_DIR')
if xdg_runtime_dir:
os.makedirs(xdg_runtime_dir, exist_ok=True)
# Separate DConf configuration from host in all cases.
env['DCONF_PROFILE'] = self._dconf_profile.get_path()
def start(self, new_session=False):
if self.system_bus:
log.info("Starting D-Bus system bus for sandbox.")
log.debug("Added environment variables: %s", self.extra_env)
self.system_bus.start(env=self.get_environment(), new_session=new_session)
self.extra_env['DBUS_SYSTEM_BUS_ADDRESS'] = self.system_bus.get_address()
log.info("Starting D-Bus session bus for sandbox.")
log.debug("Added environment variables: %s", self.extra_env)
self.session_bus.start(env=self.get_environment(), new_session=new_session)
def stop(self):
tracker_processes = []
log.info("Looking for active Tracker processes on the session bus")
for busname in self.session_bus.list_names_sync():
if busname.startswith(TRACKER_DBUS_PREFIX):
pid = self.session_bus.get_connection_unix_process_id_sync(busname)
if pid is not None:
tracker_processes.append(pid)
log.info("Terminating %i Tracker processes", len(tracker_processes))
for pid in tracker_processes:
os.kill(pid, signal.SIGTERM)
log.info("Waiting for %i Tracker processes", len(tracker_processes))
for pid in tracker_processes:
psutil.wait_pid(pid)
# We need to wait until Tracker processes have stopped before we
# terminate the D-Bus daemon, otherwise lots of criticals like this
# appear in the log output:
#
# (tracker-miner-fs:14955): GLib-GIO-CRITICAL **: 11:38:40.386: Error while sending AddMatch() message: The connection is closed
log.info("Stopping D-Bus session bus for sandbox.")
self.session_bus.stop()
if self.system_bus:
log.info("Stopping D-Bus system bus for sandbox.")
self.system_bus.stop()
def stop_daemon(self, busname):
"""Stops the daemon that owns 'busname'.
This can be used if you want to force the miner-fs to exit, for
example.
"""
log.info("Stopping daemon process that owns %s.", busname)
pid = self.daemon.get_connection_unix_process_id_sync(busname)
if pid:
os.kill(pid, signal.SIGTERM)
psutil.wait_pid(pid)
log.info("Process %i has stopped.", pid)
else:
log.info("Couldn't find a process owning %s.", busname)
def get_session_bus_connection(self):
"""Return a Gio.BusConnection to the sandbox D-Bus session bus."""
return self.session_bus.get_connection()
def get_system_bus_connection(self):
"""Return a Gio.BusConnection to the sandbox D-Bus system bus."""
return self.system_bus.get_connection()
def get_session_bus_address(self):
return self.session_bus.get_address()
def get_dconf_client(self):
return DConfClient(
self.extra_env, self.get_session_bus_address()
)
def set_config(self, schema_config_dict):
"""Set config values in multiple GSettings schemas.
Example input:
set_all({
'org.freedesktop.Tracker3.Miner.Files': {
'enable-writeback': GLib.Variant.new_boolean(False),
}
})
"""
dconf_client = self.get_dconf_client()
for schema_name, contents in schema_config_dict.items():
for key, value in contents.items():
dconf_client.write(schema_name, key, value)