Re: [PATCH] eventfd: new command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 Hi Alexander,

On Thu, Aug 19, 2010 at 06:46:41PM +0300, Alexander Shishkin wrote:
> +AC_CHECK_FUNCS([eventfd])

 please, see autoconf stuff and code for unshare(1) command. There 
 should be:

   UTIL_CHECK_SYSCALL([eventfs])

 and
 
   AM_CONDITIONAL(BUILD_EVENTFD, ...)

> +usrbin_exec_PROGRAMS += cytune setarch eventfd

   if BUILD_EVENTFD
   usrbin_exec_PROGRAMS += eventfd
   endif

 our build system has to be usable on systems without eventfd(2).

> +$ eventfd -n PINGFD -w 'printf "ping received (%d)" $__EVENTFDVAL'
> +$ eventfd -n PINGFD -e 1

 I don't like the -w options. The first horrible things is that the
 variable name is hardcoded and second things is that this feature is
 implemented by system() function. What about to implement "-w" as a
 separate command (like "-e")?

 I don't understand why your code uses fork(), you can control this
 thing from shell by "&".

 What about:

  - setup a new event FD and starts a new shell or <command>:

     $ eventfd -n <name> [<command> [<argv> ...]]

  - read value from event FD and print to stdout:

     $ eventfd -n <name> --watch

  - write value to event FD

     $ eventfd -n <name> --echo <value>


 It would be also nice to support --fd <eventfd> as an alternative to
 "-n" for watch and echo operations. The file descriptor is visible
 for example in /proc/#/fd, so you don't have to depend on env.
 variables, etc.

 See my very primitive implementation below, you can:

    $ eventfd -n PINGFD

    $ xterm &

    $ ./a -n PINGFD --wait | while read val; do \
        echo "Event value: $val"; \
      done

 and in xterm:

    $ eventfd -n PINGFD --echo 123

 and in the original session you will see

    Event value: 123

 This all is possible without fork() and system().

> +{
> +	struct pollfd fds = { .fd = fd, .events = POLLIN };
> +
> +	while (poll(&fds, 1, -1) > 0) {
> +		uint64_t efdval;
> +		size_t len;
> +		char s[BUFSIZ];
> +
> +		len = read(fd, &efdval, sizeof efdval);
> +		if (len != sizeof(uint64_t)) {
> +			perror(_("short read from eventfd"));
> +			exit(EXIT_FAILURE);
> +		}
> +
> +		snprintf(s, BUFSIZ, "%lu", efdval);

   %"PRIu64"

....

> +	fprintf(stderr, _("eventfd poll failed\n"));
> +}

 please, use err() and warn() for error/rarning messages.

> +static int writer(char *varname, uint64_t echoval)
> +{
> +	char *fdstr = getenv(varname);
> +	int fd;
> +	ssize_t len;
> +
> +	if (!fdstr) {
> +		fprintf(stderr, _("$%s is empty\n"), varname);
> +		return EXIT_FAILURE;
> +	}
> +
> +	fd = atoi(fdstr);

 I think we should be more paranoid with strings from env.variables or
 command line -- what about strtoll()?

> +	len = write(fd, &echoval, 8);
> +	if (len == -1) {
> +		perror(_("write failed"));
> +		return EXIT_FAILURE;
> +	}
> +
> +	return EXIT_SUCCESS;
> +}
> +
> +static const struct option options[] = {
> +	{ "nofork",	0, 0, 'F' },
> +	{ "echo",	1, 0, 'e' },
> +	{ "varname",	1, 0, 'n' },
> +	{ "watchcmd",	1, 0, 'w' },
> +	{ "init",	1, 0, 'i' },
> +	{ "help",	0, 0, 'h' },
> +	{ NULL,		0, 0, 0   },
> +};
> +
> +static const char *optdescs[] = {
> +	"exec the main process without forking",
> +	"echo a number into eventfd",
> +	"eventfd variable name",
> +	"command to launch upon signal arrival",
> +	"initial value of the eventfd counter",
> +	"print help message"
> +};
> +
> +static void usage(int exitcode)
> +{
> +	int i;
> +
> +	printf(_("usage: %s [OPTIONS] <program> ...\n\n"
> +		 "Create, write and poll eventfds.\nOPTIONS:\n"),
> +		program_invocation_short_name);
> +	for (i = 0; options[i].name; i++)
> +		printf("  -%c, --%-10s %s\n", options[i].val, options[i].name,
> +		       _(optdescs[i]));
>

Interesting idea :-) ... but please, use normal usage() with strings rather
than optdescs[] array. See for example sys-utils/fallocate.c.

The output from usage() should be to stderr in case of error
(EXIT_FAILURE).

> +	exit(exitcode);
> +}
> +
> +static const char optstr[] = "Fe:n:w:i:h";
> +
> +int main(int argc, char *argv[])
> +{
> +	uint64_t echoval = 0;
> +	unsigned int initval = 0;
> +	int fd, c, loptidx, nofork = 0;
> +	char *varname = "EVENTFD";
> +	char val[BUFSIZ];
> +	char **nargv;
> +	char *watchcmd = NULL;
> +
> +	for (;;) {
> +		c = getopt_long(argc, argv, optstr, options, NULL);
> +		if (c == -1)
> +			break;
> +
> +		switch (c) {
> +			case 'e':
> +				echoval = strtoeventfd(optarg);
> +				break;
> +			case 'i':
> +				initval = strtoul(optarg, NULL, 10);
> +				break;
> +			case 'n':
> +				varname = strdup(optarg);
> +				break;
> +			case 'F':
> +				nofork++;
> +				break;
> +			case 'w':
> +				watchcmd = strdup(optarg);
        

        if (!watchcmd)
            err(EXIT_FAILURE, _("out of memory"));
 ...

    Karel


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <sys/eventfd.h>
#include <inttypes.h>

int main(int argc, char *argv[])
{
	int idx = 1;
	int fd = -1;
	uint64_t val;
	char *name = NULL;

	if (strcmp(argv[idx], "-n") == 0) {
		char *x = getenv((name = argv[++idx]));
		if (x)
			fd = atoi(x);
		++idx;
	}

	if (strcmp(argv[idx], "--echo") == 0) {
		/* write to event FD */
		val = strtoumax(argv[++idx], NULL, 10);
		write(fd, &val, 8);

	} else if (strcmp(argv[idx], "--watch") == 0) {
		/* read from event FD */
		struct pollfd fds = { .fd = fd, .events = POLLIN };

		while (poll(&fds, 1, -1) > 0) {
			read(fd, &val, sizeof(val));
			printf("%ju\n", val);
			fflush(stdout);
		}

	} else if (fd == -1 && name) {
		/* setup a new event FD and start shell */
		char *nargv[] = { "/bin/bash", NULL };
		char buf[BUFSIZ];

		fd = eventfd(0, 0);
		sprintf(buf, "%d", fd);
		setenv(name, buf, 1);
		return execv(nargv[0], nargv);
	}

	return EXIT_FAILURE;
}

--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux