https://bugs.gentoo.org/695972
https://github.com/proftpd/proftpd/commit/f09f0c661621eb22cb1ce579194478007ba62866

From f09f0c661621eb22cb1ce579194478007ba62866 Mon Sep 17 00:00:00 2001
From: Justin Maggard <jmaggard@netgear.com>
Date: Tue, 10 Oct 2017 18:20:06 -0700
Subject: [PATCH] Bug #4319: Treat EINTR like EAGAIN

This bug described a situation where an ongoing transfer would be
prematurely aborted when one of our timers fired.  The timer could have
fired for an unrelated reason, but if we were in the process of reading
or writing with pr_netio_read() or pr_netio_write(), those calls would
be interrupted with errno set to EINTR, and an error would be returned.
Then pr_data_xfer() would abort the transfer.

EAGAIN was already being handled properly, and we can just use the same
treatment for EINTR so that we only respond to the timers we should
actually care about.
---
 src/data.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- a/src/data.c
+++ b/src/data.c
@@ -1143,7 +1143,7 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) {
         while (len < 0) {
           int xerrno = errno;
  
-          if (xerrno == EAGAIN) {
+          if (xerrno == EAGAIN || xerrno == EINTR) {
             /* Since our socket is in non-blocking mode, read(2) can return
              * EAGAIN if there is no data yet for us.  Handle this by
              * delaying temporarily, then trying again.
@@ -1265,7 +1265,7 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) {
       while (len < 0) {
         int xerrno = errno;
 
-        if (xerrno == EAGAIN) {
+        if (xerrno == EAGAIN || xerrno == EINTR) {
           /* Since our socket is in non-blocking mode, read(2) can return
            * EAGAIN if there is no data yet for us.  Handle this by
            * delaying temporarily, then trying again.
@@ -1362,7 +1362,7 @@ int pr_data_xfer(char *cl_buf, size_t cl_size) {
       while (bwrote < 0) {
         int xerrno = errno;
 
-        if (xerrno == EAGAIN) {
+        if (xerrno == EAGAIN || xerrno == EINTR) {
           /* Since our socket is in non-blocking mode, write(2) can return
            * EAGAIN if there is not enough from for our data yet.  Handle
            * this by delaying temporarily, then trying again.
-- 
2.23.0

