[Info-vax] Apache + mod_php performance

Dan Cross cross at spitfire.i.gajendra.net
Wed Oct 2 15:38:26 EDT 2024


In article <vdd2mr$1tq3s$4 at dont-email.me>,
Arne Vajhøj  <arne at vajhoej.dk> wrote:
>On 9/29/2024 10:03 PM, Lawrence D'Oliveiro wrote:
>> On Sun, 29 Sep 2024 21:58:45 -0400, Arne Vajhøj wrote:
>> 
>>> On 9/29/2024 9:46 PM, Lawrence D'Oliveiro wrote:
>>>>
>>>> On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:
>>>>>
>>>>> On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:
>>>>>>
>>>>>> Then it asks another process for a copy of that socket descriptor.
>>>>>> Perhaps there is one overall connection-management process that
>>>>>> accepts all new connections; if not, another worker that has that
>>>>>> socket can pass it along.
>>>>>
>>>>> It should not be a problem of copying a socket descriptor from one
>>>>> process to another process - I believe it is just an int.
>>>>>
>>>>> But will it work in the other process????
>>>>
>>>> That’s not how you do it. You pass it with the SCM_RIGHTS
>>>> ancillary-data option in Unix-family sockets
>>>> <https://manpages.debian.org/7/unix.7.en.html>.
>>>
>>> Worker A has a AF_INET socket to client so what AF_UNIX socket does it
>>> pass to worker B?
>> 
>> You can pass any FD (AF_INET socket, file, pipe, even another AF_UNIX
>> socket) over an AF_UNIX socket.
>
>Ah. Interesting. Very interesting.

Access rights passing over Unix domain sockets was introduced in
4.2BSD, in 1983: more than 40 years ago.  The basic mechanism
was updated in 4.4BSD, in 1994: 30 years ago.  Here's a working
example:

// Passing access rights between processes over Unix domain
// sockets.
//
// Dan Cross <cross at gajendra.net>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>

#include <stddef.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
recv_fd(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 structure.
	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;
}

>But I am pretty sure that it will not work on VMS.

There's some chatter that suggests Unix domain sockets were
added in OpenVMS 8.4, in 2010: 14 years ago:
https://de.openvms.org/TUD2011/Unix_Portability_Updates_and_Open_Source.pdf

I haven't checked myself; even if the basic Unix domain sockets
mechanism was added for IPC, it's not clear if the access rights
transfer functionality was also implemented.

	- Dan C.



More information about the Info-vax mailing list