Skip to content
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

Correctly locate filepath of caller to tracepoint #13

Merged
merged 2 commits into from Mar 21, 2017

Conversation

jahfer
Copy link
Contributor

@jahfer jahfer commented Feb 14, 2017

This PR will correctly infer the original caller of the method traced via Kernel.caller_locations.

Unfortunately, this introduces a major decrease in performance (a 10-minute 96-way CI run now takes > 1 hour). As a minor optimization, we're able to shortcut this expensive call for methods defined in C using rb_tracearg_path since Kernel.caller_locations cannot point to the C-code for its definition.

The only way to get a performant solution would be to have some traction on Bug #7976 in Ruby. Research into different methods of path detection have been noted in this gist: https://gist.github.com/jahfer/092e44df6f15298bae3cf47056301708

@jahfer jahfer force-pushed the find-callsite-and-callpoint branch 2 times, most recently from 2aff9c3 to 00b3b69 Compare February 15, 2017 18:26
@jahfer jahfer changed the title Split lookup of callsite and callpoint Correctly locate filepath of caller to tracepoint Feb 15, 2017
@jahfer jahfer force-pushed the find-callsite-and-callpoint branch 4 times, most recently from df8257f to b2a5f96 Compare March 2, 2017 20:00
@jahfer jahfer force-pushed the find-callsite-and-callpoint branch 5 times, most recently from 899114a to 4471438 Compare March 21, 2017 12:57
@jahfer jahfer force-pushed the find-callsite-and-callpoint branch from 4471438 to c42c834 Compare March 21, 2017 13:00
Copy link

@stevelounsbury stevelounsbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had some questions answered IRL, looks good to me 👍

// drop down to default on purpose
default:
caller_str = (caller_str == NULL) ? (caller_location(1) + 1) : caller_str;
if (caller_str != NULL)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the above statement, it seems like the else branch would never be hit? Or can caller_location(1) + 1 somehow end up being NULL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be NULL if the execution stack was length 1, which seems…unlikely? Grabbing an artifact from a CI run using this, I don't see any filepaths that get set to the else branch, so I will remove it 👍

caller_str = strtok(NULL, ":");
if (caller_str)
{
callsite.lineno = (unsigned int)strtol(caller_str, &endptr, 10);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're not actually using endptr for anything, I think you can just pass NULL.

caller_str = (caller_str == NULL) ? (caller_location(1) + 1) : caller_str;
if (caller_str != NULL)
{
char *data = strdup(caller_str);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is leaking memory, if that's of concern

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was my lousy stackoverflow debugging of a segfault in CI with strtok. I don't think it's actually needed, so I'll get rid of this as well.

Copy link

@thegedge thegedge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

caller_str = strtok(NULL, ":");
if (caller_str)
{
callsite.lineno = (unsigned int)strtol(caller_str, NULL, 10);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you'd like to set this to zero otherwise, in the rare (maybe "impossible"?) case where there's no line number in the caller string (which would result in "random" line numbers).

@jahfer jahfer force-pushed the find-callsite-and-callpoint branch 7 times, most recently from a022695 to e30f356 Compare March 21, 2017 18:59
{
strncpy((char *)callsite.filepath, caller_str, sizeof(callsite.filepath));
strtok((char *)callsite.filepath, ":");
if (caller_str = strtok(NULL, ":"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after lots of back-and-forth here, I've settled on two invocations of strtok instead of strchr since there's some extra bounds checking done by strtok that I don't want to have to reimplement.

tl;dr I got a segfault and gave up on strchr

@jahfer jahfer force-pushed the find-callsite-and-callpoint branch from e30f356 to 1a76b68 Compare March 21, 2017 19:22
@jahfer jahfer merged commit 2cf8678 into master Mar 21, 2017
@jahfer jahfer deleted the find-callsite-and-callpoint branch March 21, 2017 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants