Re: [patch 1/2] fork_connector: add a fork connector

Guillaume Thouvenin
2005-03-23T08:15:51Z

On Tue, 2005-03-22 at 10:15 -0800, Jay Lan wrote:
> Guillaume Thouvenin wrote:
> > On Mon, 2005-03-21 at 12:52 -0800, Ram wrote:
> >
> >> If a bunch of applications are listening for fork events,
> >> your patch allows any application to turn off the
> >> fork event notification? Is this the right behavior?
> >
> >
> > Yes it is. The main management is done by application so, if several
> > applications are listening for fork events you need to choose which one
> > will turn off the fork connector.
>
> It is not practical. One listener never know who else are listening
> to the fork connector.
>
> We also need to protect yet another global variable "cn_fork_enable".
>
> Also, in order to implement "cn_fork_enable" as a counter, we need
> some sort of registration to prevent an application from sending
> repeated "off" notification. One can only turn off its own switch.

I agree with the Evgeniy's ip example. I can provide a fork connector
interface utility to enable or disable the fork connector. Thus,
listeners don't have to start and stop the fork connector and they don't
have to worry about who else are listening the fork connector. It also
removes the need of registration.

I copy at the end of this email the code of the fork connector
controller application (called fcctl).

I need to add the possibility to get the state of the fork connector.
I also need to extend the fork connector to send to everyone information
when it is turned off/on.

Regards,
Guillaume

/*
* fcctl.c - Fork connector interface utility
*
* Used to turn on/off the fork connector
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>

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

#include <linux/connector.h>
#include <linux/netlink.h>

#define MESSAGE_SIZE (sizeof(struct nlmsghdr) + \
sizeof(struct cn_msg) + \
sizeof(int))

#define FORK_CN_DISABLE 0
#define FORK_CN_ENABLE 1
#define FORK_CN_UNKNOWN 2

void show_help()
{
printf("usage: fcctl {on|off}\n\n");
}

int main(int argc, char **argv)
{
int sk_nl;
int err;
int action = FORK_CN_UNKNOWN;
struct sockaddr_nl sa_nl; /* info for the netlink interface */
char buff[128]; /* must be > MESSAGE_SIZE */
struct nlmsghdr *hdr;
struct cn_msg *mesg;

if (getuid() != 0) {
printf("Only root can start/stop the fork connector\n");
return 0;
}

if (argc != 2) {
show_help();
return 0;
}

if (strcmp(argv[1], "on") == 0)
action = FORK_CN_ENABLE;
else if (strcmp(argv[1], "off") == 0)
action = FORK_CN_DISABLE;

if (action == FORK_CN_UNKNOWN) {
show_help();
return 0;
}

/*
* Create an endpoint for communication. Use the kernel user
* interface device (PF_NETLINK) which is a datagram oriented
* service (SOCK_DGRAM). The protocol used is the netfilter/iptables
* ULOG protocol (NETLINK_NFLOG)
*/
sk_nl = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_NFLOG);
if (sk_nl == -1) {
printf("socket sk_nl error");
return -1;
}

sa_nl.nl_family = AF_NETLINK;
sa_nl.nl_groups = CN_IDX_FORK;
sa_nl.nl_pid = getpid();

err = bind(sk_nl, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
if (err == -1) {
printf("binding sk_nl error");
close(sk_nl);
return -1;
}

/* Clear the buffer */
memset(buff, '\0', sizeof(buff));

/* fill the message header */
hdr = (struct nlmsghdr *)buff;

hdr->nlmsg_len = MESSAGE_SIZE;
hdr->nlmsg_type = NLMSG_DONE;
hdr->nlmsg_flags = 0;
hdr->nlmsg_seq = 0;
hdr->nlmsg_pid = getpid();

/* the message */
mesg = (struct cn_msg *)NLMSG_DATA(hdr);
mesg->id.idx = CN_IDX_FORK;
mesg->id.val = CN_VAL_FORK;
mesg->seq = 0;
mesg->ack = 0;
mesg->len = sizeof(int);
mesg->data[0] = action;

send(sk_nl, hdr, hdr->nlmsg_len, 0);

close(sk_nl);

return 0;
}