Skip to content

Commit 00a3cbd

Browse files
authored
more child-process (#18688)
Co-authored-by: pfgithub <6010774+pfgithub@users.noreply.github.com>
1 parent d291b56 commit 00a3cbd

File tree

70 files changed

+2945
-872
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2945
-872
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"scripts": {
3333
"build": "bun run build:debug",
3434
"watch": "zig build check --watch -fincremental --prominent-compile-errors --global-cache-dir build/debug/zig-check-cache --zig-lib-dir vendor/zig/lib",
35+
"watch-windows": "zig build check-windows --watch -fincremental --prominent-compile-errors --global-cache-dir build/debug/zig-check-cache --zig-lib-dir vendor/zig/lib",
3536
"bd": "(bun run --silent build:debug &> /tmp/bun.debug.build.log || (cat /tmp/bun.debug.build.log && rm -rf /tmp/bun.debug.build.log && exit 1)) && rm -f /tmp/bun.debug.build.log && ./build/debug/bun-debug",
3637
"build:debug": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -B build/debug",
3738
"build:valgrind": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_BASELINE=ON -ENABLE_VALGRIND=ON -B build/debug-valgrind",

packages/bun-types/bun.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6613,9 +6613,10 @@ declare module "bun" {
66136613
ipc?(
66146614
message: any,
66156615
/**
6616-
* The {@link Subprocess} that sent the message
6616+
* The {@link Subprocess} that received the message
66176617
*/
66186618
subprocess: Subprocess<In, Out, Err>,
6619+
handle?: unknown,
66196620
): void;
66206621

66216622
/**

packages/bun-usockets/src/bsd.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,20 @@ ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {
725725
}
726726
}
727727

728+
#if !defined(_WIN32)
729+
ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags) {
730+
while (1) {
731+
ssize_t ret = recvmsg(fd, msg, flags);
732+
733+
if (UNLIKELY(IS_EINTR(ret))) {
734+
continue;
735+
}
736+
737+
return ret;
738+
}
739+
}
740+
#endif
741+
728742
#if !defined(_WIN32)
729743
#include <sys/uio.h>
730744

@@ -783,6 +797,20 @@ ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int ms
783797
}
784798
}
785799

800+
#if !defined(_WIN32)
801+
ssize_t bsd_sendmsg(LIBUS_SOCKET_DESCRIPTOR fd, const struct msghdr *msg, int flags) {
802+
while (1) {
803+
ssize_t rc = sendmsg(fd, msg, flags);
804+
805+
if (UNLIKELY(IS_EINTR(rc))) {
806+
continue;
807+
}
808+
809+
return rc;
810+
}
811+
}
812+
#endif
813+
786814
int bsd_would_block() {
787815
#ifdef _WIN32
788816
return WSAGetLastError() == WSAEWOULDBLOCK;

packages/bun-usockets/src/context.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,15 @@ struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *
279279
return context;
280280
}
281281

282-
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_bun_socket_context_options_t options, enum create_bun_socket_error_t *err) {
282+
struct us_socket_context_t *us_create_bun_ssl_socket_context(struct us_loop_t *loop, int context_ext_size, struct us_bun_socket_context_options_t options, enum create_bun_socket_error_t *err) {
283283
#ifndef LIBUS_NO_SSL
284-
if (ssl) {
285-
/* This function will call us, again, with SSL = false and a bigger ext_size */
286-
return (struct us_socket_context_t *) us_internal_bun_create_ssl_socket_context(loop, context_ext_size, options, err);
287-
}
284+
/* This function will call us, again, with SSL = false and a bigger ext_size */
285+
return (struct us_socket_context_t *) us_internal_bun_create_ssl_socket_context(loop, context_ext_size, options, err);
288286
#endif
287+
return us_create_bun_nossl_socket_context(loop, context_ext_size);
288+
}
289289

290+
struct us_socket_context_t *us_create_bun_nossl_socket_context(struct us_loop_t *loop, int context_ext_size) {
290291
/* This path is taken once either way - always BEFORE whatever SSL may do LATER.
291292
* context_ext_size will however be modified larger in case of SSL, to hold SSL extensions */
292293

@@ -370,8 +371,8 @@ struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_co
370371
ls->s.timeout = 255;
371372
ls->s.long_timeout = 255;
372373
ls->s.flags.low_prio_state = 0;
373-
ls->s.flags.is_paused = 0;
374-
374+
ls->s.flags.is_paused = 0;
375+
ls->s.flags.is_ipc = 0;
375376
ls->s.next = 0;
376377
ls->s.flags.allow_half_open = (options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
377378
us_internal_socket_context_link_listen_socket(context, ls);
@@ -406,6 +407,7 @@ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_sock
406407
ls->s.flags.low_prio_state = 0;
407408
ls->s.flags.allow_half_open = (options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
408409
ls->s.flags.is_paused = 0;
410+
ls->s.flags.is_ipc = 0;
409411
ls->s.next = 0;
410412
us_internal_socket_context_link_listen_socket(context, ls);
411413

@@ -414,7 +416,6 @@ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_sock
414416
return ls;
415417
}
416418

417-
418419
struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_context_t *context, struct sockaddr_storage* addr, int options, int socket_ext_size) {
419420
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(addr, options);
420421
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
@@ -437,6 +438,7 @@ struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_cont
437438
socket->flags.low_prio_state = 0;
438439
socket->flags.allow_half_open = (options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
439440
socket->flags.is_paused = 0;
441+
socket->flags.is_ipc = 0;
440442
socket->connect_state = NULL;
441443

442444

@@ -563,6 +565,7 @@ int start_connections(struct us_connecting_socket_t *c, int count) {
563565
s->flags.low_prio_state = 0;
564566
s->flags.allow_half_open = (c->options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
565567
s->flags.is_paused = 0;
568+
s->flags.is_ipc = 0;
566569
/* Link it into context so that timeout fires properly */
567570
us_internal_socket_context_link_socket(s->context, s);
568571

@@ -739,6 +742,7 @@ struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_con
739742
connect_socket->flags.low_prio_state = 0;
740743
connect_socket->flags.allow_half_open = (options & LIBUS_SOCKET_ALLOW_HALF_OPEN);
741744
connect_socket->flags.is_paused = 0;
745+
connect_socket->flags.is_ipc = 0;
742746
connect_socket->connect_state = NULL;
743747
connect_socket->connect_next = NULL;
744748
us_internal_socket_context_link_socket(context, connect_socket);
@@ -843,6 +847,14 @@ void us_socket_context_on_data(int ssl, struct us_socket_context_t *context, str
843847
context->on_data = on_data;
844848
}
845849

850+
void us_socket_context_on_fd(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_fd)(struct us_socket_t *s, int fd)) {
851+
#ifndef LIBUS_NO_SSL
852+
if (ssl) return;
853+
#endif
854+
855+
context->on_fd = on_fd;
856+
}
857+
846858
void us_socket_context_on_writable(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_writable)(struct us_socket_t *s)) {
847859
#ifndef LIBUS_NO_SSL
848860
if (ssl) {

packages/bun-usockets/src/crypto/openssl.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,10 +1535,9 @@ us_internal_bun_create_ssl_socket_context(
15351535
/* Otherwise ee continue by creating a non-SSL context, but with larger ext to
15361536
* hold our SSL stuff */
15371537
struct us_internal_ssl_socket_context_t *context =
1538-
(struct us_internal_ssl_socket_context_t *)us_create_bun_socket_context(
1539-
0, loop,
1540-
sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size,
1541-
options, err);
1538+
(struct us_internal_ssl_socket_context_t *)us_create_bun_nossl_socket_context(
1539+
loop,
1540+
sizeof(struct us_internal_ssl_socket_context_t) + context_ext_size);
15421541

15431542
/* I guess this is the only optional callback */
15441543
context->on_server_name = NULL;
@@ -2080,8 +2079,8 @@ struct us_internal_ssl_socket_t *us_internal_ssl_socket_wrap_with_tls(
20802079
us_socket_context_ref(0,old_context);
20812080

20822081
enum create_bun_socket_error_t err = CREATE_BUN_SOCKET_ERROR_NONE;
2083-
struct us_socket_context_t *context = us_create_bun_socket_context(
2084-
1, old_context->loop, sizeof(struct us_wrapped_socket_context_t),
2082+
struct us_socket_context_t *context = us_create_bun_ssl_socket_context(
2083+
old_context->loop, sizeof(struct us_wrapped_socket_context_t),
20852084
options, &err);
20862085

20872086
// Handle SSL context creation failure

packages/bun-usockets/src/internal/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ struct us_socket_flags {
170170
bool allow_half_open: 1;
171171
/* 0 = not in low-prio queue, 1 = is in low-prio queue, 2 = was in low-prio queue in this iteration */
172172
unsigned char low_prio_state: 2;
173+
/* If true, the socket should be read using readmsg to support receiving file descriptors */
174+
bool is_ipc: 1;
173175

174176
} __attribute__((packed));
175177

@@ -287,6 +289,7 @@ struct us_socket_context_t {
287289
struct us_socket_t *(*on_open)(struct us_socket_t *, int is_client, char *ip,
288290
int ip_length);
289291
struct us_socket_t *(*on_data)(struct us_socket_t *, char *data, int length);
292+
struct us_socket_t *(*on_fd)(struct us_socket_t *, int fd);
290293
struct us_socket_t *(*on_writable)(struct us_socket_t *);
291294
struct us_socket_t *(*on_close)(struct us_socket_t *, int code, void *reason);
292295
// void (*on_timeout)(struct us_socket_context *);

packages/bun-usockets/src/internal/networking/bsd.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,13 @@ int bsd_addr_get_port(struct bsd_addr_t *addr);
207207
LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr);
208208

209209
ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
210+
#if !defined(_WIN32)
211+
ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags);
212+
#endif
210213
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
214+
#if !defined(_WIN32)
215+
ssize_t bsd_sendmsg(LIBUS_SOCKET_DESCRIPTOR fd, const struct msghdr *msg, int flags);
216+
#endif
211217
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
212218
int bsd_would_block();
213219

packages/bun-usockets/src/libusockets.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,10 @@ enum create_bun_socket_error_t {
264264
CREATE_BUN_SOCKET_ERROR_INVALID_CA,
265265
};
266266

267-
struct us_socket_context_t *us_create_bun_socket_context(int ssl, struct us_loop_t *loop,
267+
struct us_socket_context_t *us_create_bun_ssl_socket_context(struct us_loop_t *loop,
268268
int ext_size, struct us_bun_socket_context_options_t options, enum create_bun_socket_error_t *err);
269+
struct us_socket_context_t *us_create_bun_nossl_socket_context(struct us_loop_t *loop,
270+
int ext_size);
269271

270272
/* Delete resources allocated at creation time (will call unref now and only free when ref count == 0). */
271273
void us_socket_context_free(int ssl, us_socket_context_r context) nonnull_fn_decl;
@@ -280,6 +282,8 @@ void us_socket_context_on_close(int ssl, us_socket_context_r context,
280282
struct us_socket_t *(*on_close)(us_socket_r s, int code, void *reason));
281283
void us_socket_context_on_data(int ssl, us_socket_context_r context,
282284
struct us_socket_t *(*on_data)(us_socket_r s, char *data, int length));
285+
void us_socket_context_on_fd(int ssl, us_socket_context_r context,
286+
struct us_socket_t *(*on_fd)(us_socket_r s, int fd));
283287
void us_socket_context_on_writable(int ssl, us_socket_context_r context,
284288
struct us_socket_t *(*on_writable)(us_socket_r s));
285289
void us_socket_context_on_timeout(int ssl, us_socket_context_r context,
@@ -465,7 +469,7 @@ void us_socket_local_address(int ssl, us_socket_r s, char *nonnull_arg buf, int
465469

466470
/* Bun extras */
467471
struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds);
468-
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd);
472+
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd, int ipc);
469473
struct us_socket_t *us_socket_wrap_with_tls(int ssl, us_socket_r s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size);
470474
int us_socket_raw_write(int ssl, us_socket_r s, const char *data, int length, int msg_more);
471475
struct us_socket_t* us_socket_open(int ssl, struct us_socket_t * s, int is_client, char* ip, int ip_length);

packages/bun-usockets/src/loop.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
313313
s->flags.low_prio_state = 0;
314314
s->flags.allow_half_open = listen_socket->s.flags.allow_half_open;
315315
s->flags.is_paused = 0;
316+
s->flags.is_ipc = 0;
316317

317318
/* We always use nodelay */
318319
bsd_socket_nodelay(client_fd, 1);
@@ -391,7 +392,43 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
391392
const int recv_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
392393
#endif
393394

394-
int length = bsd_recv(us_poll_fd(&s->p), loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, LIBUS_RECV_BUFFER_LENGTH, recv_flags);
395+
int length;
396+
#if !defined(_WIN32)
397+
if(s->flags.is_ipc) {
398+
struct msghdr msg = {0};
399+
struct iovec iov = {0};
400+
char cmsg_buf[CMSG_SPACE(sizeof(int))];
401+
402+
iov.iov_base = loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING;
403+
iov.iov_len = LIBUS_RECV_BUFFER_LENGTH;
404+
405+
msg.msg_flags = 0;
406+
msg.msg_iov = &iov;
407+
msg.msg_iovlen = 1;
408+
msg.msg_name = NULL;
409+
msg.msg_namelen = 0;
410+
msg.msg_controllen = CMSG_LEN(sizeof(int));
411+
msg.msg_control = cmsg_buf;
412+
413+
length = bsd_recvmsg(us_poll_fd(&s->p), &msg, recv_flags);
414+
415+
// Extract file descriptor if present
416+
if (length > 0 && msg.msg_controllen > 0) {
417+
struct cmsghdr *cmsg_ptr = CMSG_FIRSTHDR(&msg);
418+
if (cmsg_ptr && cmsg_ptr->cmsg_level == SOL_SOCKET && cmsg_ptr->cmsg_type == SCM_RIGHTS) {
419+
int fd = *(int *)CMSG_DATA(cmsg_ptr);
420+
s = s->context->on_fd(s, fd);
421+
if(us_socket_is_closed(0, s)) {
422+
break;
423+
}
424+
}
425+
}
426+
}else{
427+
#endif
428+
length = bsd_recv(us_poll_fd(&s->p), loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, LIBUS_RECV_BUFFER_LENGTH, recv_flags);
429+
#if !defined(_WIN32)
430+
}
431+
#endif
395432

396433
if (length > 0) {
397434
s = s->context->on_data(s, loop->data.recv_buf + LIBUS_RECV_BUFFER_PADDING, length);

packages/bun-usockets/src/socket.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_e
284284
return 0;
285285
}
286286

287-
return us_socket_from_fd(ctx, socket_ext_size, fds[0]);
287+
return us_socket_from_fd(ctx, socket_ext_size, fds[0], 0);
288288
#endif
289289
}
290290

@@ -302,7 +302,7 @@ int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int hea
302302
return written < 0 ? 0 : written;
303303
}
304304

305-
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd) {
305+
struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd, int ipc) {
306306
#if defined(LIBUS_USE_LIBUV) || defined(WIN32)
307307
return 0;
308308
#else
@@ -321,6 +321,8 @@ struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socke
321321
s->flags.low_prio_state = 0;
322322
s->flags.allow_half_open = 0;
323323
s->flags.is_paused = 0;
324+
s->flags.is_ipc = 0;
325+
s->flags.is_ipc = ipc;
324326
s->connect_state = NULL;
325327

326328
/* We always use nodelay */
@@ -374,6 +376,44 @@ int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length
374376
return written < 0 ? 0 : written;
375377
}
376378

379+
#if !defined(_WIN32)
380+
/* Send a message with data and an attached file descriptor, for use in IPC. Returns the number of bytes written. If that
381+
number is less than the length, the file descriptor was not sent. */
382+
int us_socket_ipc_write_fd(struct us_socket_t *s, const char* data, int length, int fd) {
383+
if (us_socket_is_closed(0, s) || us_socket_is_shut_down(0, s)) {
384+
return 0;
385+
}
386+
387+
struct msghdr msg = {0};
388+
struct iovec iov = {0};
389+
char cmsgbuf[CMSG_SPACE(sizeof(int))];
390+
391+
iov.iov_base = (void*)data;
392+
iov.iov_len = length;
393+
394+
msg.msg_iov = &iov;
395+
msg.msg_iovlen = 1;
396+
msg.msg_control = cmsgbuf;
397+
msg.msg_controllen = CMSG_SPACE(sizeof(int));
398+
399+
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
400+
cmsg->cmsg_level = SOL_SOCKET;
401+
cmsg->cmsg_type = SCM_RIGHTS;
402+
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
403+
404+
*(int *)CMSG_DATA(cmsg) = fd;
405+
406+
int sent = bsd_sendmsg(us_poll_fd(&s->p), &msg, 0);
407+
408+
if (sent != length) {
409+
s->context->loop->data.last_write_failed = 1;
410+
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
411+
}
412+
413+
return sent < 0 ? 0 : sent;
414+
}
415+
#endif
416+
377417
void *us_socket_ext(int ssl, struct us_socket_t *s) {
378418
#ifndef LIBUS_NO_SSL
379419
if (ssl) {

0 commit comments

Comments
 (0)