Skip to content

Conversation

@jmagman
Copy link
Member

@jmagman jmagman commented Sep 18, 2020

Description

As of iOS 13, the host can't directly read the device logs from the host. #43915 connected to the VM observatory and read the log lines from the logging services.

On flutter run and flutter drive (not attach in this PR), instead of waiting to attach to the observatory, instead launch the app with the debugger and stay attached to stream in the logs from lldb. See #54781 (comment) for details. This should also reduce devicelab flakes.

This will give the tool access to:

  • The observatory port log line
  • Full native crash backtraces, including crashes on launch before the engine starts
  • dart print()
  • dart stderr.writeln, other I/O sinks
  • native logging (os_log, asserts etc)
  • Engine logs (may need follow up work to filter out the verbose category)

Notes

  • Keep the VM service connection for flutter attach. A follow up PR could attach the debugger in that scenario as well (without re-launching), and then the VM connection can be removed.
  • Keep the syslog connection for <iOS 13. I wasn't able to get this working on my iOS 9.3.6 test device, so don't regress it. If I can get that working, we can also remove idevicesyslog.

Related Issues

Fixes #44717
Fixes #44718
Fixes #54781

#39240 (fixes run/drive, not attach)
#58078 (fixes run/drive, not attach)

Mitigate #46705 (run/drive, not attach)
Will allow us to turn off mDNS fallback for drive on CI to solve iOS 14 issue #65207

Note to self: check if this fixes #19196

Tests

  • ios_deploy_tests
  • ios_device_logger_tests
  • ios_device_start_prebuilt_tests

Follow up with logging integration tests so this stops regressing.

Also, manually tested:

  • Detaching doesn't stop the app.
  • ios-deploy processes aren't leaking

Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I signed the [CLA].
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

  • No, no existing tests failed, so this is not a breaking change.
  • Yes, this is a breaking change. If not, delete the remainder of this section.

@jmagman jmagman added the platform-ios iOS applications specifically label Sep 18, 2020
@jmagman jmagman self-assigned this Sep 18, 2020
@flutter-dashboard flutter-dashboard bot added tool Affects the "flutter" command-line tool. See also t: labels. work in progress; do not review labels Sep 18, 2020
Copy link
Member Author

@jmagman jmagman Sep 18, 2020

Choose a reason for hiding this comment

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

The change in this file switches the order of fallbacks, which confused git. Now it first tries log scanning, and only if that fails, falls back to mDNS discovery.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was previously waiting and buffering for duration before sending the first message. The observatory URL was discovered faster than 200 ms in my tests, so let's not wait to process it.

@jmagman jmagman marked this pull request as ready for review September 18, 2020 17:33
Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

If this is successful should we remove the mDNS fallback entirely? Could we also remove the provisioning logic for the mDNS permissions?

// (lldb) run
// success
// 2020-09-15 13:42:25.185474-0700 Runner[477:181141] flutter: Observatory listening on http://127.0.0.1:57782/
if (line == '(lldb) run') {
Copy link
Contributor

Choose a reason for hiding this comment

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

this might deserve a const, with a doc describing where you found it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

_logger.printTrace('ios-deploy failed: $exception');
_debuggerAttached = false;
_debuggerOutput.addError(exception, stackTrace);
} on ArgumentError catch (exception, stackTrace) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will fail if ios-deploy is missing right? should we catch the error or let it crash here and solve the problem elsewhere? i.e. startup checks

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we already have those checks in place with the stamp/artifact download logic, since ios-deploy is an artifact we ship ourselves idevicesyslog. Unlike the Xcode tooling where we do lots of install checks.

// (lldb) run
// success
// 2020-09-15 13:42:25.185474-0700 Runner[477:181141] flutter: Observatory listening on http://127.0.0.1:57782/
if (line == '(lldb) run') {
Copy link
Member

Choose a reason for hiding this comment

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

Is there any way to make this test and the test for 'success' more resilient to changes in output from lldb? Maybe ignore whitespace or unexpected lines between here and 'success'?

Copy link
Member Author

Choose a reason for hiding this comment

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

run is coming from ios-deploy, and success is coming from lldb. I will make this a regex to handle whitespace differences.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added more comments and tests.

debuggerCompleter.complete(false);
return;
}
if (!debuggerAttached) {
Copy link
Member

Choose a reason for hiding this comment

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

Oh, okay. The very next line after the lldb run line doesn't have to be 'success'. We'll wait until it is. Consider updating the comment above.

Copy link
Member Author

Choose a reason for hiding this comment

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

It does have to be "success" (lldbRunCalled logic where it's being set to false if the next line isn't "success"), unless I have a bug in here.

Maybe I should change this to fail if the next line isn't "success" so it doesn't hang forever on something unexpected instead of special-casing "error: process launch failed" (and example of a non-success next line).

Copy link
Member

Choose a reason for hiding this comment

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

Ah, okay. I misread the code. My suggestion for a cleanup would be to structure this explicitly as a state machine, with an enum setting out explicitly what the states are, and a big comment explaining what/when the transitions are.

That might also make testing this code easier. I think I see below that the error paths in here could use some coverage.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added an enum, hopefully it's clearer now.

_logger.printTrace('ios-deploy exited with code $exitCode');
_debuggerAttached = false;
unawaited(stdoutSubscription.cancel());
unawaited(stderrSubscription.cancel());
Copy link
Member

Choose a reason for hiding this comment

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

Does ios-deploy have anything interesting on its stderr when it exits with an error?

Copy link
Member Author

Choose a reason for hiding this comment

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

Some stuff:
https://github.com/ios-control/ios-deploy/blob/master/src/ios-deploy/ios-deploy.m#L1741
Though nothing that's probably actionable to the developer. It's being printTraced a few lines above this.
https://github.com/flutter/flutter/pull/66092/files/e91e25e01ffa596f7e60c861b435a9c672a9a29e#diff-8d108d6a887a4f5b74f7c7d77003e795R326

They seem to put actionable errors to stdout (see _monitorIOSDeployFailure parsing below, which existed before this PR).

Copy link
Member Author

Choose a reason for hiding this comment

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

Added _monitorIOSDeployFailure to the stderr processing in case they move how that's output. Will add a test.

debuggerCompleter.complete(false);
return;
}
if (!debuggerAttached) {
Copy link
Member

Choose a reason for hiding this comment

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

Ah, okay. I misread the code. My suggestion for a cleanup would be to structure this explicitly as a state machine, with an enum setting out explicitly what the states are, and a big comment explaining what/when the transitions are.

That might also make testing this code easier. I think I see below that the error paths in here could use some coverage.

final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>['ios-deploy'],
stdout: '(lldb) run\r\nsuccess\r\nLog on attach1\r\n\r\nLog on attach2\r\n\r\n\r\n\r\nPROCESS_STOPPED\r\nLog after process exit',
Copy link
Member

Choose a reason for hiding this comment

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

Test failure modes on unexpected stdout.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

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

LGTM if LG to @zanderso

@jmagman
Copy link
Member Author

jmagman commented Sep 18, 2020

If this is successful should we remove the mDNS fallback entirely? Could we also remove the provisioning logic for the mDNS permissions?

It's still used in the attach case, which would need to trickiness like interrupting the app and printing the observatory URL to on attach (there's probably a more elegant way to do this? I don't know how to detect from an app when a debugger attaches, only how to tell if it's launched with the debugger attached).

However it will allow us to remove the mDNS permission for flutter drive, which would solve #65207.

Copy link
Member

@zanderso zanderso left a comment

Choose a reason for hiding this comment

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

lgtm

@jmagman
Copy link
Member Author

jmagman commented Sep 18, 2020

Merging on red, hopefully this will deflake things (after a few reverts no doubt)

dnfield added a commit that referenced this pull request Sep 22, 2020
dnfield added a commit that referenced this pull request Sep 22, 2020
dnfield added a commit that referenced this pull request Sep 22, 2020
dnfield added a commit that referenced this pull request Sep 22, 2020
christopherfujino added a commit to chris-forks/flutter that referenced this pull request Sep 22, 2020
jmagman added a commit that referenced this pull request Sep 22, 2020
jmagman added a commit that referenced this pull request Sep 22, 2020
jmagman added a commit to jmagman/flutter that referenced this pull request Sep 22, 2020
jmagman added a commit that referenced this pull request Sep 22, 2020
jmagman added a commit that referenced this pull request Sep 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform-ios iOS applications specifically tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

4 participants