kernel: HTTPS through wget, half-close, and /proc/<pid>/fd
busybox wget hands TLS to ssl_client over a socketpair and then does shutdown(SHUT_WR). That cut the AF_UNIX link both ways, so ssl_client's reply was a SIGPIPE and every https:// download hung. SHUT_WR is now a half-close: the peer reads EOF and can still answer. TCP sockets get shutdown() at all (tcp_shutdown for the FIN); it used to do nothing. - exec keeps ignored signals and the signal mask, as execve(2) says. - /proc/<pid>/fd: a link per descriptor -- the path it was opened by, socket:[n], pipe:[n], anon_inode:[eventpoll]. /proc/self too. The global inode bit moves above pid << 8; at 0x10000 it was /proc/256. - fstat on a socket or pipe answers S_IFSOCK / S_IFIFO instead of EINVAL. - poll, select and epoll wake as soon as a pipe, socket or input device changes, not on the next tick. - Pipes are 64 KB of lazily allocated pages, copied in blocks, with PIPE_BUF atomicity: 300 MB through `yes | head | wc` in 7 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
906318f2b6
commit
8351e0323b
15 changed files with 434 additions and 71 deletions
|
|
@ -24,22 +24,47 @@
|
|||
|
||||
#define POLL_MAX_FDS 64
|
||||
|
||||
// Sleep one timer tick, or until killed/signaled. Returns 0 to keep
|
||||
// waiting, -EINTR if the wait must be abandoned.
|
||||
static int
|
||||
poll_block_one_tick(void)
|
||||
// Bumped, under tickslock, by anything that can make a descriptor ready
|
||||
// sooner than the next tick: see poll_kick().
|
||||
static uint poll_seq;
|
||||
|
||||
// Something a poller may be waiting for has happened. The wait below sleeps
|
||||
// on the tick channel, so this wakes it now rather than at the tick.
|
||||
//
|
||||
// Without it every poll() that found nothing slept out the rest of a 10 ms
|
||||
// tick whatever arrived in the meantime. busybox's wget polls before each
|
||||
// read, and downloaded at 85 KB/s -- a segment per tick -- where apk, which
|
||||
// blocks in read() and is woken by the data, managed 5.8 MB/s over the same
|
||||
// connection. Called from the network stack's wakeup; anything else that
|
||||
// makes a file readable can call it too, and until it does it is no worse
|
||||
// than it was.
|
||||
void
|
||||
poll_kick(void)
|
||||
{
|
||||
if (myproc()->killed)
|
||||
return -EINTR;
|
||||
if (myproc()->pending_signals & ~myproc()->signal_mask)
|
||||
acquire(&tickslock);
|
||||
poll_seq++;
|
||||
release(&tickslock);
|
||||
wakeup(&ticks);
|
||||
}
|
||||
|
||||
// Sleep one timer tick, or until a poll_kick, or until killed/signaled.
|
||||
// Returns 1 if a tick went by, 0 if it was a kick -- which must not count
|
||||
// against a timeout, or a timed poll on a busy network would end early --
|
||||
// and -EINTR if the wait must be abandoned. epoll waits with it too.
|
||||
int
|
||||
poll_wait_tick(void)
|
||||
{
|
||||
struct proc *p = myproc();
|
||||
if (p->killed || (p->pending_signals & ~p->signal_mask))
|
||||
return -EINTR;
|
||||
acquire(&tickslock);
|
||||
uint t0 = ticks;
|
||||
while (ticks == t0 && !myproc()->killed &&
|
||||
!(myproc()->pending_signals & ~myproc()->signal_mask))
|
||||
uint t0 = ticks, s0 = poll_seq;
|
||||
while (ticks == t0 && poll_seq == s0 && !p->killed &&
|
||||
!(p->pending_signals & ~p->signal_mask))
|
||||
sleep(&ticks, &tickslock);
|
||||
int ticked = ticks != t0;
|
||||
release(&tickslock);
|
||||
return 0;
|
||||
return ticked;
|
||||
}
|
||||
|
||||
// Shared core: fds[] already in kernel memory. timeout_ticks < 0 means
|
||||
|
|
@ -67,9 +92,10 @@ do_poll(struct pollfd *fds, int nfds, int timeout_ticks)
|
|||
}
|
||||
if (nready > 0 || timeout_ticks == 0)
|
||||
return nready;
|
||||
if (poll_block_one_tick() < 0)
|
||||
int w = poll_wait_tick();
|
||||
if (w < 0)
|
||||
return -EINTR;
|
||||
if (timeout_ticks > 0)
|
||||
if (w > 0 && timeout_ticks > 0)
|
||||
timeout_ticks--;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,9 +241,10 @@ sys_select(void)
|
|||
}
|
||||
return nready;
|
||||
}
|
||||
if (poll_block_one_tick() < 0)
|
||||
int w = poll_wait_tick();
|
||||
if (w < 0)
|
||||
return -EINTR;
|
||||
if (timeout_ticks > 0)
|
||||
if (w > 0 && timeout_ticks > 0)
|
||||
timeout_ticks--;
|
||||
}
|
||||
}
|
||||
|
|
@ -287,9 +314,10 @@ sys_pselect6(void)
|
|||
}
|
||||
return nready;
|
||||
}
|
||||
if (poll_block_one_tick() < 0)
|
||||
int w = poll_wait_tick();
|
||||
if (w < 0)
|
||||
return -EINTR;
|
||||
if (timeout_ticks > 0)
|
||||
if (w > 0 && timeout_ticks > 0)
|
||||
timeout_ticks--;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue