[Info-vax] Apache + mod_php performance
Arne Vajhøj
arne at vajhoej.dk
Mon Oct 7 16:07:25 EDT 2024
On 10/7/2024 11:52 AM, Dan Cross wrote:
> // Demonstration of a listener process that accepts
> // incoming TCP connections and passes them to a
> // worker process over Unix domain sockets.
> //
> // Dan Cross <cross at gajendra.net>
>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <sys/uio.h>
> #include <netinet/in.h>
>
> #include <stddef.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
>
> // Sends a file descripter, `fd`, over a Unix domain socket `sd`
> // via the 4.4BSD access rights passing mechanism.
> //
> // Returns 1 on success, -1 on failure.
> int
> sendfd(int sd, int fd)
> {
> struct msghdr mh;
> struct iovec iv;
> struct cmsghdr *ptr;
> size_t len;
> int ret;
> char dummy;
>
> // Construct the control message header. Note this is
> // malloc'ed to ensure proper alignment.
> len = CMSG_SPACE(sizeof(int));
> ptr = malloc(len);
> if (ptr == NULL)
> return -1;
> memset(ptr, 0, len);
> ptr->cmsg_len = len;
> ptr->cmsg_level = SOL_SOCKET;
> ptr->cmsg_type = SCM_RIGHTS;
> memcpy(CMSG_DATA(ptr), &fd, sizeof(int));
>
> // We send a single byte of dummy data in case the
> // implementation does not pass control data with an
> // otherwise empty data transfer.
> dummy = 0;
> memset(&iv, 0, sizeof(iv));
> iv.iov_base = &dummy;
> iv.iov_len = 1;
>
> // Construct the message header. Points to the dummy
> // data and the control message header.
> memset(&mh, 0, sizeof(mh));
> mh.msg_name = NULL;
> mh.msg_namelen = 0;
> mh.msg_iov = &iv;
> mh.msg_iovlen = 1;
> mh.msg_control = (caddr_t)ptr;
> mh.msg_controllen = len;
> mh.msg_flags = 0;
>
> // Loop in case there's no room in the kernel buffer
> // to send. Cf.Stevens et al.
> do {
> ret = sendmsg(sd, &mh, 0);
> } while (ret == 0);
> free(ptr);
>
> return ret;
> }
>
> // Receives a file descriptor over the Unix domain socket `sd`
> // and store it into `*fdp` on success.
> //
> // Returns 1 on success, 0 on EOF, -1 on error.
> int
> recvfd(int sd, int *fdp)
> {
> struct msghdr mh;
> struct iovec iv;
> struct cmsghdr *ptr;
> size_t len;
> int ret;
> char dummy;
>
> if (fdp == NULL)
> return -1;
>
> // Allocate space for the control message.
> len = CMSG_SPACE(sizeof(int));
> ptr = malloc(len);
> if (ptr == NULL)
> return -1;
>
> // Fill in an iovec to receive one byte of dummy data.
> // Required on some systems that do not pass control
> // messages on empty data transfers.
> memset(&iv, 0, sizeof(iv));
> iv.iov_base = &dummy;
> iv.iov_len = 1;
>
> // Fill in the msghdr structure. `recvmsg(2)` will
> // update it.
> memset(&mh, 0, sizeof(mh));
> mh.msg_name = NULL;
> mh.msg_namelen = 0;
> mh.msg_iov = &iv;
> mh.msg_iovlen = 1;
> mh.msg_control = ptr;
> mh.msg_controllen = len;
> mh.msg_flags = 0;
>
> ret = recvmsg(sd, &mh, 0);
> if (ret <= 0) {
> free(ptr);
> return ret;
> }
> if (mh.msg_flags != 0) {
> free(ptr);
> return -1;
> }
> memcpy(fdp, CMSG_DATA(ptr), sizeof(int));
> free(ptr);
>
> return 1;
> }
>
> void
> dispatcher(int sdworker, int port)
> {
> int sd, nsd;
> struct sockaddr_in sa;
> struct sockaddr_in client;
> socklen_t clientlen;
>
> sd = socket(AF_INET, SOCK_STREAM, 0);
> if (sd < 0) {
> perror("socket");
> close(sdworker);
> exit(EXIT_FAILURE);
> }
> memset(&sa, 0, sizeof sa);
> sa.sin_family = AF_INET;
> sa.sin_port = htons((unsigned short)port);
> sa.sin_addr.s_addr = htonl(INADDR_ANY);
> if (bind(sd, (struct sockaddr *)&sa, sizeof sa) < 0) {
> perror("bind");
> close(sdworker);
> close(sd);
> exit(EXIT_FAILURE);
> }
> if (listen(sd, 255) < 0) {
> perror("listen");
> close(sdworker);
> close(sd);
> exit(EXIT_FAILURE);
> }
>
> memset(&client, 0, sizeof client);
> clientlen = sizeof client;
> while ((nsd = accept(sd, (struct sockaddr *)&client, &clientlen)) >= 0) {
> if (sendfd(sdworker, nsd) < 0) {
> perror("sendfd");
> close(sdworker);
> close(nsd);
> close(sd);
> exit(EXIT_FAILURE);
> }
> close(nsd);
> }
> }
>
> static void
> echo(int sd)
> {
> char *p;
> char buf[1024];
> ssize_t nb, wb;
>
> for (;;) {
> nb = read(sd, buf, sizeof buf);
> if (nb < 0)
> perror("read");
> if (nb <= 0)
> return;
> p = buf;
> while (nb > 0) {
> wb = write(sd, p, nb);
> if (wb < 0)
> perror("write");
> if (wb <= 0)
> return;
> nb -= wb;
> p += wb;
> }
> }
> }
>
> void
> worker(int sddispatcher)
> {
> int sd;
>
> while (recvfd(sddispatcher, &sd) > 0) {
> echo(sd);
> close(sd);
> }
> }
>
> int
> main(void)
> {
> int sds[2];
> pid_t pid;
>
> if (socketpair(AF_UNIX, SOCK_STREAM, 0, sds) > 0) {
> perror("socketpair");
> exit(EXIT_FAILURE);
> }
>
> for (int k = 0; k < 3; k++) {
> pid = fork();
> if (pid < 0) {
> perror("fork");
> exit(EXIT_FAILURE);
> }
> if (pid == 0) { // Child
> close(sds[0]);
> worker(sds[1]);
> exit(EXIT_SUCCESS);
> }
> }
> close(sds[1]);
> dispatcher(sds[0], 8200);
>
> return EXIT_SUCCESS;
> }
$ cc zz
len = CMSG_SPACE(sizeof(int));
.........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is
implicitly declared as a function.
at line number 33 in file DKA0:[arne]zz.c;1
mh.msg_control = (caddr_t)ptr;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_control" is not a member of "mh".
at line number 56 in file DKA0:[arne]zz.c;1
mh.msg_controllen = len;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_controllen" is not a member of
"mh".
at line number 57 in file DKA0:[arne]zz.c;1
mh.msg_flags = 0;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
at line number 58 in file DKA0:[arne]zz.c;1
mh.msg_control = ptr;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_control" is not a member of "mh".
at line number 100 in file DKA0:[arne]zz.c;1
mh.msg_controllen = len;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_controllen" is not a member of
"mh".
at line number 101 in file DKA0:[arne]zz.c;1
mh.msg_flags = 0;
...^
%CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
at line number 102 in file DKA0:[arne]zz.c;1
if (mh.msg_flags != 0) {
.......^
%CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
at line number 108 in file DKA0:[arne]zz.c;1
pid = fork();
............^
%CC-I-IMPLICITFUNC, In this statement, the identifier "fork" is
implicitly declared as a function.
at line number 201 in file DKA0:[arne]zz.c;1
Arne
More information about the Info-vax
mailing list