File 0493-erts-Improve-driver_SUITE-smp_select.patch of Package erlang

From bde3ec5d818d1948e8a0008a22bcb2e247ce3cc6 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Tue, 20 Nov 2018 17:30:25 +0100
Subject: [PATCH 1/2] erts: Improve driver_SUITE:smp_select

to better detect an actual missing ready_input event
on slow machines (valgrind)
and without wasting time with long sleep on fast machines.
---
 erts/emulator/test/driver_SUITE.erl              | 17 ++++++++-
 erts/emulator/test/driver_SUITE_data/chkio_drv.c | 45 +++++++++++++++++++-----
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index 6f5d639d04..bd62708aa7 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -1754,7 +1754,7 @@ smp_select0(Config) ->
     ProcFun = fun()-> io:format("Worker ~p starting\n",[self()]),	
                       Port = open_port({spawn, DrvName}, []),
                       smp_select_loop(Port, 100000),
-                      sleep(1000), % wait for driver to handle pending events
+                      smp_select_done(Port),
                       true = erlang:port_close(Port),
                       Master ! {ok,self()},
                       io:format("Worker ~p finished\n",[self()])
@@ -1784,6 +1784,21 @@ smp_select_loop(Port, N) ->
               smp_select_loop(Port, N-1)
     end.
 
+smp_select_done(Port) ->
+    case erlang:port_control(Port, ?CHKIO_SMP_SELECT, "done") of
+        "wait" ->
+            receive
+                {Port, done} ->
+                    ok
+            after 10*1000 ->
+                    %% Seems we have a lost ready_input event.
+                    %% Go ahead anyway, port will crash VM when closed.
+                    ok
+            end;
+
+        "ok" -> ok
+    end.
+
 smp_select_wait([], _) ->
     ok;
 smp_select_wait(Pids, TimeoutMsg) ->
diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c
index ee8f28e8b1..baf0ca9f11 100644
--- a/erts/emulator/test/driver_SUITE_data/chkio_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c
@@ -90,7 +90,7 @@ typedef struct chkio_smp_select {
     int next_read;
     int next_write;
     int first_write;
-    enum {Closed, Opened, Selected, Waiting} state;
+    enum {Closed, Opened, Selected, Waiting, WaitingDone} state;
     int wasSelected;
     unsigned rand_state;
 }ChkioSmpSelect;
@@ -292,18 +292,20 @@ stop_steal_aux(ChkioDrvData *cddp)
 static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port)
 {	
     switch (pip->state) {
+    case WaitingDone:
     case Waiting: {
 	int word;
-	fprintf(stderr, "Closing pipe in state Waiting. Event lost?\n");
+	fprintf(stderr, "Closing pipe in state Waiting*. Event lost?\r\n");
 	for (;;) {
 	    int bytes = read(pip->read_fd, &word, sizeof(word));
 	    if (bytes != sizeof(word)) {
 		if (bytes != 0) {
-		    fprintf(stderr, "Failed to read from pipe, bytes=%d, errno=%d\n", bytes, errno);
+		    fprintf(stderr, "Failed to read from pipe, bytes=%d, errno=%d\r\n",
+                            bytes, errno);
 		}
 		break;
 	    }
-	    fprintf(stderr, "Read from pipe: %d\n", word);
+	    fprintf(stderr, "Read from pipe: %d\r\n", word);
 	}
 	abort();
     }
@@ -318,6 +320,8 @@ static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port)
 	close(pip->write_fd);
 	pip->state = Closed;
 	break;
+    case Closed:
+        break;
     }
     driver_free(pip);
 }
@@ -526,7 +530,7 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
 	    printf("Read event on uninitiated pipe %d\n", fd);
 	    abort(); 
 	}
-	if (pip->state != Selected && pip->state != Waiting) { 
+	if (pip->state != Selected && pip->state != Waiting && pip->state != WaitingDone) {
 	    printf("Read event on pipe in strange state %d\n", pip->state);
 	    abort(); 
 	}
@@ -536,9 +540,9 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
 	inPipe = (pip->next_write - pip->next_read);
 	if (inPipe == 0) {
 	    bytes = read(pip->read_fd, &word, sizeof(word));
-	    printf("Unexpected empty pipe, expected %u -> %u, bytes=%d, word=%d, written=%d\n",
-		   pip->next_read, pip->next_write-1, bytes, word,
-		   (pip->next_write - pip->first_write));
+	    printf("Unexpected empty pipe: ptr=%p, fds=%d->%d, read bytes=%d, word=%d, written=%d\n",
+                   pip, pip->write_fd, pip->read_fd,
+		   bytes, word, (pip->next_write - pip->first_write));
 	    /*abort();
     	      Allow unexpected events as it's been seen to be triggered by epoll
 	      on Linux. Most of the time the unwanted events are filtered by
@@ -564,7 +568,20 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event)
 	    TRACEF(("Read %d from fd=%d\n", word, fd));
 	    pip->next_read++;
 	}
-	pip->state = Selected; /* not Waiting anymore */
+        if (pip->state == WaitingDone) {
+            if (pip->next_write == pip->next_read) {
+                /* All data read, send {Port, done} */
+                ErlDrvTermData spec[] = {ERL_DRV_PORT, driver_mk_port(cddp->port),
+                                         ERL_DRV_ATOM, driver_mk_atom("done"),
+                                         ERL_DRV_TUPLE, 2};
+                erl_drv_output_term(driver_mk_port(cddp->port),
+                                    spec, sizeof(spec) / sizeof(spec[0]));
+                pip->state = Selected;
+            }
+        }
+        else {
+            pip->state = Selected; /* not Waiting anymore */
+        }
 	break;
     }
     case CHKIO_DRV_USE:
@@ -962,6 +979,16 @@ chkio_drv_control(ErlDrvData drv_data,
     }
     case CHKIO_SMP_SELECT: {
 	ChkioSmpSelect* pip = (ChkioSmpSelect*) cddp->test_data;
+        if (len == 4 && memcmp(buf, "done", 4) == 0) {
+            if (pip && pip->state == Waiting) {
+                pip->state = WaitingDone;
+                res_str = "wait";
+            }
+            else
+                res_str = "ok";
+            res_len = -1;
+            break;
+        }
 	if (pip == NULL) {
 	    erl_drv_mutex_lock(smp_pipes_mtx);
 	    if (smp_pipes) {
-- 
2.16.4