mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 07:22:34 +00:00
New option sitout-eio
This commit is contained in:
parent
c2196d6f15
commit
d10dd8a03e
9 changed files with 59 additions and 14 deletions
5
CHANGES
5
CHANGES
|
@ -45,6 +45,11 @@ Features:
|
|||
before exit. Signal USR1 logs actual values.
|
||||
Tests: OPTION_STATISTICS SIGUSR1_STATISTICS
|
||||
|
||||
Added option sitout-eio to specify a timerange in which EIO on the pty
|
||||
of a sub process is tolerated.
|
||||
Red Hat issue 1853102 related.
|
||||
Thanks to Jonathan Casiot for sending an initial patch.
|
||||
|
||||
Corrections:
|
||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
||||
0, its last sent data might have been lost depending on timing of read/
|
||||
|
|
|
@ -2823,6 +2823,12 @@ label(OPTION_PTY_INTERVAL)dit(bf(tt(pty-interval=<seconds>)))
|
|||
periodically checks the HUP condition using tt(poll()) to find if the pty's
|
||||
slave side has been opened. The default polling interval is 1s. Use the
|
||||
pty-interval option [link(timeval)(TYPE_TIMEVAL)] to change this value.
|
||||
label(OPTION_SITOUT_EIO)dit(bf(tt(sitout-eio=<timeval>)))
|
||||
The login program in Linux closes its tty/pty and reopens it for security
|
||||
reasons. During this time the pty master would get EIO on I/O operations and
|
||||
might terminate. With this option socat() tolerates EIO for the specified
|
||||
time. Please note that in this state socat() blocks traffic in both
|
||||
directions, even when it is not related to this channel.
|
||||
enddit()
|
||||
|
||||
|
||||
|
|
6
sycls.c
6
sycls.c
|
@ -547,7 +547,11 @@ ssize_t Read(int fd, void *buf, size_t count) {
|
|||
_errno = errno;
|
||||
if (!diag_in_handler) diag_flush();
|
||||
#if WITH_SYCLS
|
||||
Debug1("read -> "F_Zd, result);
|
||||
if (result < 0) {
|
||||
Debug2("read -> "F_Zd" (errno=%d)", result, _errno);
|
||||
} else {
|
||||
Debug1("read -> "F_Zd, result);
|
||||
}
|
||||
#endif /* WITH_SYCLS */
|
||||
errno = _errno;
|
||||
return result;
|
||||
|
|
|
@ -21,6 +21,7 @@ const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_P
|
|||
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||
const struct optdesc opt_ptmx = { "ptmx", NULL, OPT_PTMX, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
|
||||
#endif
|
||||
const struct optdesc opt_sitout_eio = { "sitout-eio", NULL, OPT_SITOUT_EIO, GROUP_PTY, PH_INIT, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.exec.sitout_eio), XIO_SIZEOF(para.exec.sitout_eio) };
|
||||
|
||||
#if WITH_EXEC || WITH_SYSTEM
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ extern const struct optdesc opt_fdout;
|
|||
extern const struct optdesc opt_path;
|
||||
extern const struct optdesc opt_pipes;
|
||||
extern const struct optdesc opt_pty;
|
||||
extern const struct optdesc opt_sitout_eio;
|
||||
extern const struct optdesc opt_openpty;
|
||||
extern const struct optdesc opt_ptmx;
|
||||
extern const struct optdesc opt_stderr;
|
||||
|
|
1
xio.h
1
xio.h
|
@ -234,6 +234,7 @@ typedef struct single {
|
|||
struct {
|
||||
pid_t pid; /* child PID, with EXEC: */
|
||||
int fdout; /* use fd for output if two pipes */
|
||||
struct timeval sitout_eio;
|
||||
} exec;
|
||||
#if WITH_READLINE
|
||||
struct {
|
||||
|
|
|
@ -1482,6 +1482,7 @@ const struct optname optionnames[] = {
|
|||
#ifdef SIOCSPGRP
|
||||
IF_SOCKET ("siocspgrp", &opt_siocspgrp)
|
||||
#endif
|
||||
IF_PTY ("sitout-eio", &opt_sitout_eio)
|
||||
IF_TUN ("slave", &opt_iff_slave)
|
||||
IF_SOCKET ("sndbuf", &opt_so_sndbuf)
|
||||
IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late)
|
||||
|
|
|
@ -644,6 +644,7 @@ enum e_optcode {
|
|||
#ifdef SIOCSPGRP
|
||||
OPT_SIOCSPGRP,
|
||||
#endif
|
||||
OPT_SITOUT_EIO,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
OPT_SO_ACCEPTCONN,
|
||||
#endif /* SO_ACCEPTCONN */
|
||||
|
|
51
xioread.c
51
xioread.c
|
@ -75,23 +75,48 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
|||
break;
|
||||
|
||||
case XIOREAD_PTY:
|
||||
do {
|
||||
{
|
||||
int eio = 0;
|
||||
bool m = false; /* loop message printed? */
|
||||
while (true) {
|
||||
do {
|
||||
bytes = Read(pipe->fd, buff, bufsiz);
|
||||
} while (bytes < 0 && errno == EINTR);
|
||||
if (bytes < 0) {
|
||||
} while (bytes < 0 && errno == EINTR);
|
||||
if (bytes < 0) {
|
||||
_errno = errno;
|
||||
if (_errno == EIO) {
|
||||
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
||||
return 0;
|
||||
} else {
|
||||
Error4("read(%d, %p, "F_Zu"): %s",
|
||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
||||
if (_errno != EIO) {
|
||||
Error4("read(%d, %p, "F_Zu"): %s", pipe->fd, buff, bufsiz, strerror(_errno));
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
errno = _errno;
|
||||
return -1;
|
||||
if (pipe->para.exec.sitout_eio.tv_sec == 0 &&
|
||||
pipe->para.exec.sitout_eio.tv_usec == 0) {
|
||||
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
||||
return 0;
|
||||
}
|
||||
if (!m) {
|
||||
/* Starting first iteration: calc and report */
|
||||
/* Round up to 10ms */
|
||||
eio = 100*pipe->para.exec.sitout_eio.tv_sec +
|
||||
(pipe->para.exec.sitout_eio.tv_usec+9999)/10000;
|
||||
Notice3("xioread(fd=%d): EIO, sitting out %u.%02lus for recovery", pipe->fd, eio/100, (unsigned long)eio%100);
|
||||
m = true;
|
||||
}
|
||||
poll(NULL, 0, 10);
|
||||
if (--eio <= 0) {
|
||||
/* Timeout */
|
||||
Error4("read(%d, %p, "F_Zu"): %s", pipe->fd, buff, bufsiz, strerror(_errno));
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
/* Not reached */
|
||||
} else
|
||||
break; /* no error */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return bytes;
|
||||
break;
|
||||
|
||||
#if WITH_READLINE
|
||||
case XIOREAD_READLINE:
|
||||
|
|
Loading…
Reference in a new issue