<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[174626] trunk/Tools</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/174626">174626</a></dd>
<dt>Author</dt> <dd>dfarler@apple.com</dd>
<dt>Date</dt> <dd>2014-10-10 17:03:39 -0700 (Fri, 10 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] LayoutTestRelay should detect EOF and properly signal underlying DRT/WKTR
https://bugs.webkit.org/show_bug.cgi?id=137527

Reviewed by Simon Fraser.

NSFileHandle doesn't notify of EOF in its readability handler.
Use a dispatch_source_t and an event handler that is called when reading is possible.
In the handler block, do a run-of-the-mill read(2) from standard input and
detect EOF in the usual way by checking that zero bytes were read.

Once an EOF is received, the FIFOs are disconnected, the simulator app
is killed, and the relay exits with status 0.

* LayoutTestRelay/LayoutTestRelay/LTRelayController.m:
(-[LTRelayController initWithDevice:productDir:appPath:identifierSuffix:dumpToolArguments:]):
(-[LTRelayController didDisconnect]):
(-[LTRelayController didConnect]):
(-[LTRelayController launchApp]):
Rename &quot;dispatchSource&quot; to &quot;simulatorAppExitDispatchSource&quot; to prevent any
confusion with this new dispatch source, called &quot;standardInputDispatchSource&quot;.
(-[LTRelayController finish]): Added.
(-[LTRelayController readFileHandle:]): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsLayoutTestRelayLayoutTestRelayLTRelayControllerm">trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (174625 => 174626)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2014-10-10 23:49:23 UTC (rev 174625)
+++ trunk/Tools/ChangeLog        2014-10-11 00:03:39 UTC (rev 174626)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2014-10-10  David Farler  &lt;dfarler@apple.com&gt;
+
+        [iOS] LayoutTestRelay should detect EOF and properly signal underlying DRT/WKTR
+        https://bugs.webkit.org/show_bug.cgi?id=137527
+
+        Reviewed by Simon Fraser.
+
+        NSFileHandle doesn't notify of EOF in its readability handler.
+        Use a dispatch_source_t and an event handler that is called when reading is possible.
+        In the handler block, do a run-of-the-mill read(2) from standard input and
+        detect EOF in the usual way by checking that zero bytes were read.
+
+        Once an EOF is received, the FIFOs are disconnected, the simulator app
+        is killed, and the relay exits with status 0.
+
+        * LayoutTestRelay/LayoutTestRelay/LTRelayController.m:
+        (-[LTRelayController initWithDevice:productDir:appPath:identifierSuffix:dumpToolArguments:]):
+        (-[LTRelayController didDisconnect]):
+        (-[LTRelayController didConnect]):
+        (-[LTRelayController launchApp]):
+        Rename &quot;dispatchSource&quot; to &quot;simulatorAppExitDispatchSource&quot; to prevent any
+        confusion with this new dispatch source, called &quot;standardInputDispatchSource&quot;.
+        (-[LTRelayController finish]): Added.
+        (-[LTRelayController readFileHandle:]): Deleted.
+
</ins><span class="cx"> 2014-10-10  KwangHyuk Kim  &lt;hyuki.kim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Crash on facebook.com
</span></span></pre></div>
<a id="trunkToolsLayoutTestRelayLayoutTestRelayLTRelayControllerm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m (174625 => 174626)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m        2014-10-10 23:49:23 UTC (rev 174625)
+++ trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m        2014-10-11 00:03:39 UTC (rev 174626)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> #import &lt;CoreSimulator/CoreSimulator.h&gt;
</span><span class="cx"> 
</span><span class="cx"> @interface LTRelayController ()
</span><del>-@property (readonly, strong) NSFileHandle *standardInput;
</del><ins>+@property (readonly, strong) dispatch_source_t standardInputDispatchSource;
</ins><span class="cx"> @property (readonly, strong) NSFileHandle *standardOutput;
</span><span class="cx"> @property (readonly, strong) NSFileHandle *standardError;
</span><span class="cx"> @property (readonly, strong) NSString *uniqueAppPath;
</span><span class="lines">@@ -58,10 +58,26 @@
</span><span class="cx">         _originalAppIdentifier = [NSDictionary dictionaryWithContentsOfFile:[_originalAppPath stringByAppendingPathComponent:@&quot;Info.plist&quot;]][(NSString *)kCFBundleIdentifierKey];
</span><span class="cx">         _identifierSuffix = suffix;
</span><span class="cx">         _dumpToolArguments = arguments;
</span><del>-        _standardInput = [NSFileHandle fileHandleWithStandardInput];
</del><ins>+        _standardInputDispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, STDIN_FILENO, 0, dispatch_get_main_queue());
</ins><span class="cx">         _standardOutput = [NSFileHandle fileHandleWithStandardOutput];
</span><span class="cx">         _standardError = [NSFileHandle fileHandleWithStandardError];
</span><span class="cx"> 
</span><ins>+        dispatch_source_set_event_handler(_standardInputDispatchSource, ^{
+            uint8_t buffer[1024];
+            ssize_t len = read(STDIN_FILENO, buffer, sizeof(buffer));
+            if (len &gt; 0) {
+                @try {
+                    [[[self relay] outputStream] write:buffer maxLength:len];
+                } @catch (NSException *e) {
+                    // Broken pipe - the dump tool crashed. Time to die.
+                    [self didCrashWithMessage:nil];
+                }
+            } else {
+                // EOF Received on the relay's standard input.
+                [self finish];
+            }
+        });
+
</ins><span class="cx">         _relay = [[LTPipeRelay alloc] initWithPrefix:[@&quot;/tmp&quot; stringByAppendingPathComponent:[self uniqueAppIdentifier]]];
</span><span class="cx">         [_relay setRelayDelegate:self];
</span><span class="cx">     }
</span><span class="lines">@@ -87,18 +103,6 @@
</span><span class="cx">     return [[[self originalAppIdentifier] componentsSeparatedByString:@&quot;.&quot;] lastObject];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)readFileHandle:(NSFileHandle *)fileHandle
-{
-    @try {
-        NSData *data = [fileHandle availableData];
-        [[[self relay] outputStream] write:[data bytes] maxLength:[data length]];
-    } @catch (NSException *e) {
-        // Broken pipe - the dump tool crashed. Time to die.
-        [self didCrashWithMessage:nil];
-    }
-}
-
-
</del><span class="cx"> - (void)didReceiveStdoutData:(NSData *)data
</span><span class="cx"> {
</span><span class="cx">     [[self standardOutput] writeData:data];
</span><span class="lines">@@ -111,15 +115,12 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)didDisconnect
</span><span class="cx"> {
</span><del>-    [[self standardInput] setReadabilityHandler:nil];
</del><ins>+    dispatch_suspend([self standardInputDispatchSource]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)didConnect
</span><span class="cx"> {
</span><del>-    [[self standardInput] setReadabilityHandler: ^(NSFileHandle *fileHandle)
-    {
-        [self readFileHandle:fileHandle];
-    }];
</del><ins>+    dispatch_resume([self standardInputDispatchSource]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)didCrashWithMessage:(NSString *)message
</span><span class="lines">@@ -204,13 +205,13 @@
</span><span class="cx">     [self setPid:pid];
</span><span class="cx"> 
</span><span class="cx">     dispatch_queue_t queue = dispatch_get_main_queue();
</span><del>-    dispatch_source_t dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, [self pid], DISPATCH_PROC_EXIT, queue);
-    [self setAppDispatchSource:dispatchSource];
-    dispatch_source_set_event_handler(dispatchSource, ^{
-        dispatch_source_cancel(dispatchSource);
</del><ins>+    dispatch_source_t simulatorAppExitDispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, [self pid], DISPATCH_PROC_EXIT, queue);
+    [self setAppDispatchSource:simulatorAppExitDispatchSource];
+    dispatch_source_set_event_handler(simulatorAppExitDispatchSource, ^{
+        dispatch_source_cancel(simulatorAppExitDispatchSource);
</ins><span class="cx">         [self didCrashWithMessage:nil];
</span><span class="cx">     });
</span><del>-    dispatch_resume(dispatchSource);
</del><ins>+    dispatch_resume(simulatorAppExitDispatchSource);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)start
</span><span class="lines">@@ -221,4 +222,11 @@
</span><span class="cx">     [[self relay] connect];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)finish
+{
+    [[self relay] disconnect];
+    [self killApp];
+    exit(EXIT_SUCCESS);
+}
+
</ins><span class="cx"> @end
</span></span></pre>
</div>
</div>

</body>
</html>