• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

spesmilo / electrum / 5169326363246592

18 May 2025 04:54PM UTC coverage: 59.527% (-0.003%) from 59.53%
5169326363246592

Pull #9840

CirrusCI

SomberNight
lnchannel: persist error sent by remote peer into db

If a force-close happens due to e.g. a feerate disagreement or an invalid signature, etc,
and the remote peer sends us an error, it can be useful if users can provide us with this error.
If the user does not have logging enabled when the error is sent, without this persistence it will likely get lost.
Pull Request #9840: lnchannel: persist error sent by remote peer into db

7 of 14 new or added lines in 2 files covered. (50.0%)

18 existing lines in 6 files now uncovered.

21585 of 36261 relevant lines covered (59.53%)

2.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/electrum/utils/stacktracer.py
1
#!/usr/bin/env python
2
#
3
# Copyright (C) 2010 Laszlo Nagy (nagylzs)
4
#
5
# Permission is hereby granted, free of charge, to any person
6
# obtaining a copy of this software and associated documentation files
7
# (the "Software"), to deal in the Software without restriction,
8
# including without limitation the rights to use, copy, modify, merge,
9
# publish, distribute, sublicense, and/or sell copies of the Software,
10
# and to permit persons to whom the Software is furnished to do so,
11
# subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be
14
# included in all copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
# SOFTWARE.
24
#
25
# Taken from: https://code.activestate.com/recipes/577334-how-to-debug-deadlocked-multi-threaded-programs/
26

27

UNCOV
28
"""Stack tracer for multi-threaded applications.
29
Useful for debugging deadlocks and hangs.
30

31
Usage:
32
    import stacktracer
33
    stacktracer.trace_start("trace.html", interval=5)
34
    ...
35
    stacktracer.trace_stop()
36

37
This will create a file named "trace.html" showing the stack traces of all threads,
38
updated every 5 seconds.
39
"""
40

41
import os
×
42
import sys
×
43
import threading
×
44
import time
×
45
import traceback
×
46
from typing import Optional
×
47

48
# 3rd-party dependency:
49
from pygments import highlight
×
50
from pygments.lexers import PythonLexer
×
51
from pygments.formatters import HtmlFormatter
×
52

53

54
def _thread_from_id(ident) -> Optional[threading.Thread]:
×
55
    return threading._active.get(ident)
×
56

57

58
def stacktraces():
×
59
    """Taken from http://bzimmer.ziclix.com/2008/12/17/python-thread-dumps/"""
60
    code = []
×
61
    for thread_id, stack in sys._current_frames().items():
×
62
        thread = _thread_from_id(thread_id)
×
63
        code.append(f"\n# thread_id={thread_id}. thread={thread}")
×
64
        for filename, lineno, name, line in traceback.extract_stack(stack):
×
65
            code.append(f'File: "{filename}", line {lineno}, in {name}')
×
66
            if line:
×
67
                code.append("  %s" % (line.strip()))
×
68

69
    return highlight("\n".join(code), PythonLexer(), HtmlFormatter(
×
70
        full=False,
71
        # style="native",
72
        noclasses=True,
73
    ))
74

75

76
class TraceDumper(threading.Thread):
×
77
    """Dump stack traces into a given file periodically.
78

79
    # written by nagylzs
80
    """
81

82
    def __init__(self, fpath, interval, auto):
×
83
        """
84
        @param fpath: File path to output HTML (stack trace file)
85
        @param auto: Set flag (True) to update trace continuously.
86
            Clear flag (False) to update only if file not exists.
87
            (Then delete the file to force update.)
88
        @param interval: In seconds: how often to update the trace file.
89
        """
90
        assert (interval > 0.1)
×
91
        self.auto = auto
×
92
        self.interval = interval
×
93
        self.fpath = os.path.abspath(fpath)
×
94
        self.stop_requested = threading.Event()
×
95
        threading.Thread.__init__(self)
×
96

97
    def run(self):
×
98
        while not self.stop_requested.is_set():
×
99
            time.sleep(self.interval)
×
100
            if self.auto or not os.path.isfile(self.fpath):
×
101
                self.dump_stacktraces()
×
102

103
    def stop(self):
×
104
        self.stop_requested.set()
×
105
        self.join()
×
106
        try:
×
107
            if os.path.isfile(self.fpath):
×
108
                os.unlink(self.fpath)
×
109
        except OSError:
×
110
            pass
×
111

112
    def dump_stacktraces(self):
×
113
        with open(self.fpath, "w+") as fout:
×
114
            fout.write(stacktraces())
×
115

116

117
_tracer = None  # type: Optional[TraceDumper]
×
118

119

120
def trace_start(fpath, interval=5, *, auto=True):
×
121
    """Start tracing into the given file."""
122
    global _tracer
123
    if _tracer is None:
×
124
        _tracer = TraceDumper(fpath, interval, auto)
×
125
        _tracer.daemon = True
×
126
        _tracer.start()
×
127
    else:
128
        raise Exception("Already tracing to %s" % _tracer.fpath)
×
129

130

131
def trace_stop():
×
132
    """Stop tracing."""
133
    global _tracer
134
    if _tracer is None:
×
135
        raise Exception("Not tracing, cannot stop.")
×
136
    else:
137
        _tracer.stop()
×
138
        _tracer = None
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc