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
|
|
@ -230,6 +230,7 @@ sockclose(struct socket *s)
|
|||
s->ref = 0;
|
||||
wakeup(&s->nqueue); // an accept() blocked on this listener
|
||||
release(&stab.lock);
|
||||
poll_kick(); // the peer's poll() sees the hangup now
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -459,6 +460,7 @@ sockread_fds(struct socket *s, char *addr, int n, struct file **fout, int *nfout
|
|||
// on a full buffer that this call has just made room in.
|
||||
wakeup(&s->nwrite);
|
||||
release(&stab.lock);
|
||||
poll_kick(); // a writer polling for room
|
||||
|
||||
// Outside the lock, because fileclose can sleep.
|
||||
if(fout){
|
||||
|
|
@ -520,7 +522,7 @@ sockwrite_fds(struct socket *s, char *addr, int n, struct file **f, int nf)
|
|||
// look for it. Same contract as a pipe with no reader: a signal, then an
|
||||
// error. A process that writes to a dead connection and is not told about
|
||||
// it spins forever believing it is making progress.
|
||||
if(s->peer == 0){
|
||||
if(s->peer == 0 || s->wr_shut){
|
||||
release(&stab.lock);
|
||||
sigsend(myproc()->pid, SIGPIPE);
|
||||
return -EPIPE;
|
||||
|
|
@ -569,6 +571,9 @@ sockwrite_fds(struct socket *s, char *addr, int n, struct file **f, int nf)
|
|||
|
||||
wakeup(&s->peer->nread);
|
||||
release(&stab.lock);
|
||||
// poll() and epoll waiters, now rather than at the next tick: an X client
|
||||
// and its server talk over these, a request and a reply at a time.
|
||||
poll_kick();
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -854,6 +859,7 @@ sockconnect(struct socket *s, uint dev, uint64 ino)
|
|||
wakeup(&srv->nqueue); // an accept() may be blocked on this
|
||||
|
||||
release(&stab.lock);
|
||||
poll_kick(); // or a listener in poll(), as Xorg's is
|
||||
|
||||
// Deliberately does *not* wait for accept(). On Unix a queued connection is
|
||||
// already established: the client may write, and the bytes sit in the
|
||||
|
|
@ -872,6 +878,9 @@ sockconnect(struct socket *s, uint dev, uint64 ino)
|
|||
int
|
||||
sock_shutdown(struct socket *s, int how)
|
||||
{
|
||||
if(s->domain == AF_INET)
|
||||
return inet_shutdown(s->inet, how);
|
||||
|
||||
acquire(&stab.lock);
|
||||
if(s->state != SS_CONNECTED){
|
||||
release(&stab.lock);
|
||||
|
|
@ -882,9 +891,20 @@ sock_shutdown(struct socket *s, int how)
|
|||
s->peer_closed = 1;
|
||||
wakeup(&s->nread);
|
||||
}
|
||||
if(how == SHUT_WR || how == SHUT_RDWR)
|
||||
if(how == SHUT_RDWR)
|
||||
orphan_peer(s);
|
||||
else if(how == SHUT_WR){
|
||||
// Half-close: the peer sees EOF once it has read what is there, and the
|
||||
// link stays, so its reply still reaches us. Cutting the link here made
|
||||
// the reply a SIGPIPE -- busybox wget does exactly this to ssl_client.
|
||||
s->wr_shut = 1;
|
||||
if(s->peer){
|
||||
s->peer->peer_closed = 1;
|
||||
wakeup(&s->peer->nread);
|
||||
}
|
||||
}
|
||||
release(&stab.lock);
|
||||
poll_kick();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue