Skip to content

Commit

Permalink
[runtime] Improve diagnostics/behavior in case of failure to contact …
Browse files Browse the repository at this point in the history
…the IDE when debugging. (#5029)

When debugging watchOS apps on device, we wait forever [1] for a connection to
be established to the IDE (iOS apps wait for only 2 seconds, but that's
because the app will be killed after a while, which we avoid on watchOS by
attaching the native debugger).

Unfortunately our error handling was not quite optimal, which meant that if
the connection to the IDE failed, we'd wait forever instead of launching the
app without attaching the debugger.

So improve this, by printing "Waiting for connection to the IDE..." messages
while trying to connect, and printing detailed log messages if the
connection attempt fails (as well as terminating the wait and launching the
watch app).

[1] In this case forever technically means "1 hour".
  • Loading branch information
rolfbjarne committed Oct 24, 2018
1 parent d2a9a57 commit ad67a39
Showing 1 changed file with 37 additions and 9 deletions.
46 changes: 37 additions & 9 deletions runtime/monotouch-debug.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
static bool debugging_configured = false;
static bool profiler_configured = false;
static bool config_timedout = false;
static bool connection_failed = false;
static DebuggingMode debugging_mode = DebuggingModeWifi;
static const char *connection_mode = "default"; // this is set from the cmd line, can be either 'usb', 'wifi', 'http' or 'none'

Expand Down Expand Up @@ -393,29 +394,46 @@ -(void) URLSession: (NSURLSession *) session task: (NSURLSessionTask *) task did
gettimeofday(&wait_tv, NULL);

int timeout;
int iterations = 1;
#if TARGET_OS_WATCH && !TARGET_OS_SIMULATOR
// When debugging on a watch device, we ensure that a native debugger is attached as well
// (since otherwise the launch sequence takes so long that watchOS kills us).
// Ensuring that a native debugger is attached when debugging also makes it possible
// to not wait at all when a native debugger is not attached, which would otherwise
// slow down every debug launch. And *that* allows us to wait for as long as we wish
// when debugging.
timeout = 3600;
timeout = 10;
iterations = 360;
#else
timeout = 2;
#endif
wait_ts.tv_sec = wait_tv.tv_sec + timeout;
wait_ts.tv_nsec = wait_tv.tv_usec * 1000;

pthread_mutex_lock (&mutex);
while (!debugging_configured && !config_timedout) {
if (pthread_cond_timedwait (&cond, &mutex, &wait_ts) == ETIMEDOUT)
config_timedout = true;
while (!debugging_configured && !config_timedout && !connection_failed) {
if (pthread_cond_timedwait (&cond, &mutex, &wait_ts) == ETIMEDOUT) {
iterations--;
if (iterations <= 0) {
config_timedout = true;
} else {
LOG (PRODUCT ": Waiting for connection to the IDE...")
// Try again
gettimeofday(&wait_tv, NULL);
wait_ts.tv_sec = wait_tv.tv_sec + timeout;
wait_ts.tv_nsec = wait_tv.tv_usec * 1000;
}
}
}
pthread_mutex_unlock (&mutex);

if (!config_timedout)
if (connection_failed) {
LOG (PRODUCT ": Debugger not loaded (failed to connect to the IDE).\n");
} else if (config_timedout) {
LOG (PRODUCT ": Debugger not loaded (timed out while trying to connect to the IDE).\n");
} else {
monotouch_load_debugger ();
}
} else {
LOG (PRODUCT ": Not connecting to the IDE, debug has been disabled\n");
}
Expand Down Expand Up @@ -772,6 +790,7 @@ int sdb_recv (void *buf, int len)
static NSString *connected_ip = NULL;
static pthread_cond_t connected_event = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t connected_mutex = PTHREAD_MUTEX_INITIALIZER;
static int pending_connections = 0;

void
xamarin_connect_http (NSMutableArray *ips)
Expand Down Expand Up @@ -803,6 +822,7 @@ int sdb_recv (void *buf, int len)
}
pthread_mutex_unlock (&connected_mutex);

pending_connections = [ips count];
for (int i = 0; i < [ips count]; i++) {
XamarinHttpConnection *connection = [[[XamarinHttpConnection alloc] init] autorelease];
connection.ip = [ips objectAtIndex: i];
Expand All @@ -811,25 +831,33 @@ int sdb_recv (void *buf, int len)
[connection connect: [ips objectAtIndex: i] port: monodevelop_port completionHandler: ^void (bool success)
{
LOG_HTTP ("Connected: %@: %i", connection, success);
pthread_mutex_lock (&connected_mutex);
if (success) {
pthread_mutex_lock (&connected_mutex);
if (connected_connection == NULL) {
connected_ip = [connection ip];
connected_connection = connection;
pthread_cond_signal (&connected_event);
}
pthread_mutex_unlock (&connected_mutex);
}
pending_connections--;
pthread_cond_signal (&connected_event);
pthread_mutex_unlock (&connected_mutex);
}];
}

unique_request = false;

LOG_HTTP ("Will wait for connections");
pthread_mutex_lock (&connected_mutex);
while (connected_connection == NULL)
while (connected_connection == NULL && pending_connections > 0)
pthread_cond_wait (&connected_event, &connected_mutex);
pthread_mutex_unlock (&connected_mutex);
if (connected_connection == NULL) {
pthread_mutex_lock (&mutex);
connection_failed = true;
pthread_cond_signal (&cond);
pthread_mutex_unlock (&mutex);
break;
}
LOG_HTTP ("Connection received fd: %i", connected_connection.fileDescriptor);
} while (monotouch_process_connection (connected_connection.fileDescriptor));

Expand Down

1 comment on commit ad67a39

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

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

Build was (probably) aborted

🔥 Jenkins job (on internal Jenkins) failed in stage(s) 'Test run' 🔥 : hudson.AbortException: script returned exit code 2

Build succeeded
API Diff (from stable)
ℹ️ API Diff (from PR only) (please review changes)
Generator Diff (no change)
🔥 Test run failed 🔥

Test results

3 tests failed, 0 tests skipped, 223 tests passed.

Failed tests

  • monotouch-test/watchOS - simulator/Debug: TimedOut
  • MTouch tests/NUnit: Failed (Execution failed with exit code 2)
  • Mac Binding Projects/Mac: TimedOut

Please sign in to comment.