-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Debugger hook/breakpoint for issue reporting from the Swift runtime #10293
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
Conversation
@swift-ci please test |
Build failed |
@swift-ci please test |
Build failed |
Build failed |
Remove some of these leading underscores. The exported function should have one underscore and everything else should have zero. |
@swift-ci please test |
Build failed |
Build failed |
fprintf(stderr, "%s ", oldAccess); | ||
if (oldPC) { | ||
dumpStackTraceEntry(0, oldPC, /*shortOutput=*/true); | ||
fprintf(stderr, " (0x%lx).\n", (uintptr_t)oldPC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this line-ending fprintf
come before the dumpStackTraceEntry
call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not trying to change the text output with this patch, so I think this is okay. Notice the /*shortOutput=*/true
, so the whole line looks like:
Previous access (a modification) started at module`your_function+0xaa (0x1000a0cd).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok.
uint64_t threadID; | ||
uintptr_t numFrames; | ||
void **frames; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to describe the # of frames to skip here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it makes sense here: Since the runtime needs to provide the frames itself, it should already strip away any uninteresting frames.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point!
const char *errorType; | ||
|
||
// Description of the current thread's stack position. | ||
const char *currentStackDescription; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#
of frames to skip?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good suggestion, I'll add it. It may get tricky to know the right value, though, because we need to know what is inlined and what is not. But it seems to be controllable enough in the two current use cases (implicit objc entrypoints and exclusivity violations).
include/swift/Runtime/Debug.h
Outdated
const char *description; | ||
const char *filename; | ||
uintptr_t line; | ||
uintptr_t column; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the exclusive access to member check using this, or is it intended for SE-0160? It's fiendishly close to describing Fix-Its (we're missing end line/column and replacement text).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant for SE-0160, and potentially for future uses as "notes" for runtime issues. I found out that the objc thunks don't have debug info, so the debugger won't point to the declaration on its own.
Any suggestions?
We could also drop these "related objects" completely, and just provide a stacktrace. Users would then have to figure out where the declaration is themselves by looking at stderr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add in debug info for these deprecated @objc
thunks, which points at the declaration. However, that won't capture the location at which we should insert the @objc
in the source.
To be fully general w.r.t. notes with Fix-Its would require something like:
struct RuntimeFixIt {
const char *filename;
uintptr_t startLine; // text in [startLine:startColumn, endLine:endColumn) gets replaced with replacementText
uintptr_t startColumn;
uintptr_t endLine;
uintptr_t endColumn;
const char *replacementText;
}
and then both RuntimeErrorDetails
and RelatedObject
would get:
uintptr_t numFixIts;
RuntimeFixIt *fixIts;
Note that having Fix-Its like these for RuntimeErrorDetails
means SE-0160 wouldn't need RelatedObjects
. That said, if we add the Fix-Its and rename RelatedObject
to Note
(or RuntimeNote
, or whatever), we'll have mirrored the diagnostic information that both the Swift and Clang frontends have... which is defensible and likely to capture everything we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the RelatedObjects
from this patch. I'll try to re-introduce it in a proper way (and bumb the ABI of this struct to "2") in a subsequent patch. Sounds good?
stdlib/public/runtime/SwiftObject.mm
Outdated
asprintf(&nullTerminatedFilename, "%*s", (int)filenameLength, filename); | ||
|
||
RuntimeErrorDetails::RelatedObject methodDeclaration = { | ||
.description = "Method declaration", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe "Method declaration; add '@objc' here"
@swift-ci please test |
Build failed |
Build failed |
…structure is passed to the debugger and describes extra information about a fatal error or a non-fatal warning, which should be logged as a runtime issue. This debugger hook is then used from two places, which currently only log to stderr: - Runtime exclusivity violations. - Swift 3 implicit Obj-C entrypoints. A subsequent LLDB support will be able to catch these callbacks and show the runtime issues in a better way than just logging them to stderr. When the debugger is not attached, this shouldn't have any effect.
@swift-ci please test |
Build failed |
Build failed |
@DougGregor is this okay to land? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This implements a debugger hook (breakpoint) API and data structure. This structure is passed to the debugger and describes extra information about a fatal error or a non-fatal warning, which should be logged as a runtime issue.
This debugger hook is then used from two places, which currently only log to stderr:
A subsequent LLDB support will be able to catch these callbacks and show the runtime issues in a better way than just logging them to stderr. When the debugger is not attached, this shouldn't have any effect.