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