From: 
Subject: Debian changes

The Debian packaging of pyshark is maintained in git, using a workflow
similar to the one described in dgit-maint-merge(7).
The Debian delta is represented by this one combined patch; there isn't a
patch queue that can be represented as a quilt series.

A detailed breakdown of the changes is available from their canonical
representation -- git commits in the packaging repository.
For example, to see the changes made by the Debian maintainer in the first
upload of upstream version 1.2.3, you could use:

    % git clone https://git.dgit.debian.org/pyshark
    % cd pyshark
    % git log --oneline 1.2.3..debian/1.2.3-1 -- . ':!debian'

(If you have dgit, use `dgit clone pyshark`, rather than plain `git clone`.)

We don't use debian/source/options single-debian-patch because it has bugs.
Therefore, NMUs etc. may nevertheless have made additional patches.

---

diff --git a/src/pyshark/cache.py b/src/pyshark/cache.py
index 78f13ed..0de585f 100644
--- a/src/pyshark/cache.py
+++ b/src/pyshark/cache.py
@@ -1,11 +1,11 @@
 import pathlib
 import shutil
 
-import appdirs
+import platformdirs
 
 
 def get_cache_dir(tshark_version) -> pathlib.Path:
-    cache_dir = pathlib.Path(appdirs.user_cache_dir(appname="pyshark", version=tshark_version))
+    cache_dir = pathlib.Path(platformdirs.user_cache_dir(appname="pyshark", version=tshark_version))
     if not cache_dir.exists():
         cache_dir.mkdir(parents=True)
     return cache_dir
diff --git a/src/pyshark/capture/capture.py b/src/pyshark/capture/capture.py
index 31fcd2a..3884067 100644
--- a/src/pyshark/capture/capture.py
+++ b/src/pyshark/capture/capture.py
@@ -67,8 +67,8 @@ class Capture:
         self._running_processes = set()
         self._decode_as = decode_as
         self._disable_protocol = disable_protocol
-        self._log = logging.Logger(
-            self.__class__.__name__, level=self.DEFAULT_LOG_LEVEL)
+        self._log = logging.getLogger(f"{self.__class__.__name__}_{id(self)}")
+        self._log.setLevel(self.DEFAULT_LOG_LEVEL)
         self._closed = False
         self._custom_parameters = custom_parameters
         self._eof_reached = False
@@ -92,6 +92,25 @@ class Capture:
             standards = ", ".join(self.SUPPORTED_ENCRYPTION_STANDARDS)
             raise UnknownEncyptionStandardException(f"Only the following standards are supported: {standards}.")
 
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        # Remove attributes that cannot be pickled (asyncio objects, logger, generator)
+        for key in ('_log', 'eventloop', '_running_processes', '_stderr_handling_tasks',
+                    '_packet_generator'):
+            state.pop(key, None)
+        return state
+
+    def __setstate__(self, state):
+        self.__dict__.update(state)
+        self._log = logging.getLogger(f"{self.__class__.__name__}_{id(self)}")
+        self._log.setLevel(self.DEFAULT_LOG_LEVEL)
+        self._running_processes = set()
+        self._stderr_handling_tasks = []
+        self.eventloop = None
+        self._setup_eventloop()
+        if hasattr(self, 'input_filepath'):
+            self._packet_generator = self._packets_from_tshark_sync()
+
     def __getitem__(self, item):
         """Gets the packet in the given index.
 
@@ -167,7 +186,10 @@ class Capture:
     def _setup_eventloop(self):
         """Sets up a new eventloop as the current one according to the OS."""
         if os.name == "nt":
-            current_eventloop = asyncio.get_event_loop_policy().get_event_loop()
+            try:
+                current_eventloop = asyncio.get_event_loop()
+            except RuntimeError:
+                current_eventloop = None
             if isinstance(current_eventloop, asyncio.ProactorEventLoop):
                 self.eventloop = current_eventloop
             else:
@@ -180,14 +202,11 @@ class Capture:
                 asyncio.set_event_loop(self.eventloop)
         else:
             try:
-                self.eventloop = asyncio.get_event_loop_policy().get_event_loop()
+                self.eventloop = asyncio.get_event_loop()
             except RuntimeError:
-                if threading.current_thread() != threading.main_thread():
-                    # Ran not in main thread, make a new eventloop
-                    self.eventloop = asyncio.new_event_loop()
-                    asyncio.set_event_loop(self.eventloop)
-                else:
-                    raise
+                # Python 3.10+: get_event_loop() no longer creates a new loop automatically
+                self.eventloop = asyncio.new_event_loop()
+                asyncio.set_event_loop(self.eventloop)
             if os.name == "posix" and isinstance(threading.current_thread(), threading._MainThread):
                 # The default child watchers (ThreadedChildWatcher) attach_loop method is empty!
                 # While using pyshark with ThreadedChildWatcher, asyncio could raise a ChildProcessError
@@ -196,9 +215,10 @@ class Capture:
                 # Using the SafeChildWatcher fixes this issue, but it is slower.
                 # SafeChildWatcher O(n) -> large numbers of processes are slow
                 # ThreadedChildWatcher O(1) -> independent of process number
-                # asyncio.get_child_watcher().attach_loop(self.eventloop)
-                asyncio.set_child_watcher(asyncio.SafeChildWatcher())
-                asyncio.get_child_watcher().attach_loop(self.eventloop)
+                # Removed in Python 3.14; child watcher API no longer needed.
+                if hasattr(asyncio, 'set_child_watcher'):
+                    asyncio.set_child_watcher(asyncio.SafeChildWatcher())
+                    asyncio.get_child_watcher().attach_loop(self.eventloop)
 
     def _packets_from_tshark_sync(self, packet_count=None, existing_process=None):
         """Returns a generator of packets.
@@ -397,8 +417,12 @@ class Capture:
             await self._cleanup_subprocess(process)
         self._running_processes.clear()
 
-        # Wait for all stderr handling to finish
-        await asyncio.gather(*self._stderr_handling_tasks)
+        # Cancel stderr tasks — after killing the process, the StreamReader may not
+        # deliver EOF on Python 3.12+, so we cancel rather than waiting indefinitely.
+        for task in self._stderr_handling_tasks:
+            task.cancel()
+        await asyncio.gather(*self._stderr_handling_tasks, return_exceptions=True)
+        self._stderr_handling_tasks.clear()
 
     def __del__(self):
         if self._running_processes:
diff --git a/src/pyshark/tshark/output_parser/tshark_xml.py b/src/pyshark/tshark/output_parser/tshark_xml.py
index 51fc698..795c588 100644
--- a/src/pyshark/tshark/output_parser/tshark_xml.py
+++ b/src/pyshark/tshark/output_parser/tshark_xml.py
@@ -22,7 +22,7 @@ class TsharkXmlParser(BaseTsharkOutputParser):
         self._psml_structure = None
 
     async def get_packets_from_stream(self, stream, existing_data, got_first_packet=True):
-        if self._parse_summaries:
+        if self._parse_summaries and self._psml_structure is None:
             existing_data = await self._get_psml_struct(stream)
         return await super().get_packets_from_stream(stream, existing_data, got_first_packet=got_first_packet)
 
diff --git a/src/pyshark/tshark/tshark.py b/src/pyshark/tshark/tshark.py
index 3d920a1..47d1f5f 100644
--- a/src/pyshark/tshark/tshark.py
+++ b/src/pyshark/tshark/tshark.py
@@ -1,4 +1,5 @@
 """Module used for the actual running of TShark"""
+import configparser
 import json
 
 from packaging import version
@@ -35,7 +36,10 @@ def get_process_path(tshark_path=None, process_name="tshark"):
     # Check if `config.ini` exists in the current directory or the pyshark directory
     config = get_config()
     if config:
-        possible_paths.append(config.get(process_name, f"{process_name}_path"))
+        try:
+            possible_paths.append(config.get(process_name, f"{process_name}_path"))
+        except configparser.NoSectionError:
+            pass
 
     # Add the user provided path to the search list
     if tshark_path is not None:
@@ -138,8 +142,8 @@ def get_ek_field_mapping(tshark_path=None):
     mapping = json.loads(
         mapping,
         object_pairs_hook=_duplicate_object_hook)["mappings"]
-    # If using wireshark 4, the key "mapping" contains what we want,
-    if "dynamic" in mapping and "properties" in mapping:
+    # If using wireshark 4+, the key "mapping" contains what we want,
+    if "properties" in mapping:
         pass
     # if using wireshark 3.5 to < 4 the data in "mapping.doc",
     elif "doc" in mapping:
diff --git a/src/setup.py b/src/setup.py
index bd027a6..f618da7 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -9,7 +9,7 @@ setup(
     version="0.6",
     packages=find_packages(),
     package_data={'': ['*.ini', '*.pcapng']},
-    install_requires=['lxml', 'termcolor', 'packaging', 'appdirs'],
+    install_requires=['lxml', 'termcolor', 'packaging', 'platformdirs'],
     tests_require=['pytest'],
     url="https://github.com/KimiNewt/pyshark",
     license="MIT",
diff --git a/src/tox.ini b/src/tox.ini
index 0ce4e57..44416da 100644
--- a/src/tox.ini
+++ b/src/tox.ini
@@ -3,7 +3,7 @@ envlist = py{35,36,37,38,39,310}
 
 [testenv]
 deps =
-    appdirs
+    platformdirs
     termcolor
     pytest
     mock
