mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +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.
|
before exit. Signal USR1 logs actual values.
|
||||||
Tests: OPTION_STATISTICS SIGUSR1_STATISTICS
|
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:
|
Corrections:
|
||||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
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/
|
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
|
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
|
slave side has been opened. The default polling interval is 1s. Use the
|
||||||
pty-interval option [link(timeval)(TYPE_TIMEVAL)] to change this value.
|
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()
|
enddit()
|
||||||
|
|
||||||
|
|
||||||
|
|
6
sycls.c
6
sycls.c
|
@ -547,7 +547,11 @@ ssize_t Read(int fd, void *buf, size_t count) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (!diag_in_handler) diag_flush();
|
if (!diag_in_handler) diag_flush();
|
||||||
#if WITH_SYCLS
|
#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 */
|
#endif /* WITH_SYCLS */
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -21,6 +21,7 @@ const struct optdesc opt_openpty = { "openpty", NULL, OPT_OPENPTY, GROUP_P
|
||||||
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||||
const struct optdesc opt_ptmx = { "ptmx", NULL, OPT_PTMX, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_ptmx = { "ptmx", NULL, OPT_PTMX, GROUP_PTY, PH_BIGEN, TYPE_BOOL, OFUNC_SPEC };
|
||||||
#endif
|
#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
|
#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_path;
|
||||||
extern const struct optdesc opt_pipes;
|
extern const struct optdesc opt_pipes;
|
||||||
extern const struct optdesc opt_pty;
|
extern const struct optdesc opt_pty;
|
||||||
|
extern const struct optdesc opt_sitout_eio;
|
||||||
extern const struct optdesc opt_openpty;
|
extern const struct optdesc opt_openpty;
|
||||||
extern const struct optdesc opt_ptmx;
|
extern const struct optdesc opt_ptmx;
|
||||||
extern const struct optdesc opt_stderr;
|
extern const struct optdesc opt_stderr;
|
||||||
|
|
1
xio.h
1
xio.h
|
@ -234,6 +234,7 @@ typedef struct single {
|
||||||
struct {
|
struct {
|
||||||
pid_t pid; /* child PID, with EXEC: */
|
pid_t pid; /* child PID, with EXEC: */
|
||||||
int fdout; /* use fd for output if two pipes */
|
int fdout; /* use fd for output if two pipes */
|
||||||
|
struct timeval sitout_eio;
|
||||||
} exec;
|
} exec;
|
||||||
#if WITH_READLINE
|
#if WITH_READLINE
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -1482,6 +1482,7 @@ const struct optname optionnames[] = {
|
||||||
#ifdef SIOCSPGRP
|
#ifdef SIOCSPGRP
|
||||||
IF_SOCKET ("siocspgrp", &opt_siocspgrp)
|
IF_SOCKET ("siocspgrp", &opt_siocspgrp)
|
||||||
#endif
|
#endif
|
||||||
|
IF_PTY ("sitout-eio", &opt_sitout_eio)
|
||||||
IF_TUN ("slave", &opt_iff_slave)
|
IF_TUN ("slave", &opt_iff_slave)
|
||||||
IF_SOCKET ("sndbuf", &opt_so_sndbuf)
|
IF_SOCKET ("sndbuf", &opt_so_sndbuf)
|
||||||
IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late)
|
IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late)
|
||||||
|
|
|
@ -644,6 +644,7 @@ enum e_optcode {
|
||||||
#ifdef SIOCSPGRP
|
#ifdef SIOCSPGRP
|
||||||
OPT_SIOCSPGRP,
|
OPT_SIOCSPGRP,
|
||||||
#endif
|
#endif
|
||||||
|
OPT_SITOUT_EIO,
|
||||||
#ifdef SO_ACCEPTCONN
|
#ifdef SO_ACCEPTCONN
|
||||||
OPT_SO_ACCEPTCONN,
|
OPT_SO_ACCEPTCONN,
|
||||||
#endif /* 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;
|
break;
|
||||||
|
|
||||||
case XIOREAD_PTY:
|
case XIOREAD_PTY:
|
||||||
do {
|
{
|
||||||
|
int eio = 0;
|
||||||
|
bool m = false; /* loop message printed? */
|
||||||
|
while (true) {
|
||||||
|
do {
|
||||||
bytes = Read(pipe->fd, buff, bufsiz);
|
bytes = Read(pipe->fd, buff, bufsiz);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (_errno == EIO) {
|
if (_errno != EIO) {
|
||||||
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
Error4("read(%d, %p, "F_Zu"): %s", pipe->fd, buff, bufsiz, strerror(_errno));
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
errno = _errno;
|
||||||
return 0;
|
return -1;
|
||||||
} else {
|
|
||||||
Error4("read(%d, %p, "F_Zu"): %s",
|
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
|
||||||
}
|
}
|
||||||
errno = _errno;
|
if (pipe->para.exec.sitout_eio.tv_sec == 0 &&
|
||||||
return -1;
|
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
|
#if WITH_READLINE
|
||||||
case XIOREAD_READLINE:
|
case XIOREAD_READLINE:
|
||||||
|
|
Loading…
Reference in a new issue