Author: pjd Date: Fri Jan 28 21:56:47 2011 New Revision: 218044 URL: http://svn.freebsd.org/changeset/base/218044
Log: Add function to assert that the only descriptors we have open are the ones we expect to be open. Also assert that they point at expected type. Because openlog(3) API is unable to tell us descriptor number it is using, we have to close syslog socket, remember assert message in local buffer and if we fail on assertion, reopen syslog socket and log the message. MFC after: 1 week Modified: head/sbin/hastd/hastd.c head/sbin/hastd/hastd.h Modified: head/sbin/hastd/hastd.c ============================================================================== --- head/sbin/hastd/hastd.c Fri Jan 28 21:52:37 2011 (r218043) +++ head/sbin/hastd/hastd.c Fri Jan 28 21:56:47 2011 (r218044) @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/linker.h> #include <sys/module.h> +#include <sys/stat.h> #include <sys/wait.h> #include <assert.h> @@ -119,6 +120,146 @@ descriptors_cleanup(struct hast_resource pjdlog_fini(); } +static const char * +dtype2str(mode_t mode) +{ + + if (S_ISBLK(mode)) + return ("block device"); + else if (S_ISCHR(mode)) + return ("character device"); + else if (S_ISDIR(mode)) + return ("directory"); + else if (S_ISFIFO(mode)) + return ("pipe or FIFO"); + else if (S_ISLNK(mode)) + return ("symbolic link"); + else if (S_ISREG(mode)) + return ("regular file"); + else if (S_ISSOCK(mode)) + return ("socket"); + else if (S_ISWHT(mode)) + return ("whiteout"); + else + return ("unknown"); +} + +void +descriptors_assert(const struct hast_resource *res, int pjdlogmode) +{ + char msg[256]; + struct stat sb; + long maxfd; + bool isopen; + mode_t mode; + int fd; + + /* + * At this point descriptor to syslog socket is closed, so if we want + * to log assertion message, we have to first store it in 'msg' local + * buffer and then open syslog socket and log it. + */ + msg[0] = '\0'; + + maxfd = sysconf(_SC_OPEN_MAX); + if (maxfd < 0) { + pjdlog_errno(LOG_WARNING, "sysconf(_SC_OPEN_MAX) failed"); + maxfd = 16384; + } + for (fd = 0; fd <= maxfd; fd++) { + if (fstat(fd, &sb) == 0) { + isopen = true; + mode = sb.st_mode; + } else if (errno == EBADF) { + isopen = false; + mode = 0; + } else { + isopen = true; /* silence gcc */ + mode = 0; /* silence gcc */ + snprintf(msg, sizeof(msg), + "Unable to fstat descriptor %d: %s", fd, + strerror(errno)); + } + if (fd == STDIN_FILENO || fd == STDOUT_FILENO || + fd == STDERR_FILENO) { + if (!isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d (%s) is closed, but should be open.", + fd, (fd == STDIN_FILENO ? "stdin" : + (fd == STDOUT_FILENO ? "stdout" : "stderr"))); + break; + } + } else if (fd == proto_descriptor(res->hr_event)) { + if (!isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d (event) is closed, but should be open.", + fd); + break; + } + if (!S_ISSOCK(mode)) { + snprintf(msg, sizeof(msg), + "Descriptor %d (event) is %s, but should be %s.", + fd, dtype2str(mode), dtype2str(S_IFSOCK)); + break; + } + } else if (fd == proto_descriptor(res->hr_ctrl)) { + if (!isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d (ctrl) is closed, but should be open.", + fd); + break; + } + if (!S_ISSOCK(mode)) { + snprintf(msg, sizeof(msg), + "Descriptor %d (ctrl) is %s, but should be %s.", + fd, dtype2str(mode), dtype2str(S_IFSOCK)); + break; + } + } else if (res->hr_role == HAST_ROLE_SECONDARY && + fd == proto_descriptor(res->hr_remotein)) { + if (!isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d (remote in) is closed, but should be open.", + fd); + break; + } + if (!S_ISSOCK(mode)) { + snprintf(msg, sizeof(msg), + "Descriptor %d (remote in) is %s, but should be %s.", + fd, dtype2str(mode), dtype2str(S_IFSOCK)); + break; + } + } else if (res->hr_role == HAST_ROLE_SECONDARY && + fd == proto_descriptor(res->hr_remoteout)) { + if (!isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d (remote out) is closed, but should be open.", + fd); + break; + } + if (!S_ISSOCK(mode)) { + snprintf(msg, sizeof(msg), + "Descriptor %d (remote out) is %s, but should be %s.", + fd, dtype2str(mode), dtype2str(S_IFSOCK)); + break; + } + } else { + if (isopen) { + snprintf(msg, sizeof(msg), + "Descriptor %d is open (%s), but should be closed.", + fd, dtype2str(mode)); + break; + } + } + } + if (msg[0] != '\0') { + pjdlog_init(pjdlogmode); + pjdlog_prefix_set("[%s] (%s) ", res->hr_name, + role2str(res->hr_role)); + PJDLOG_ABORT("%s", msg); + } +} + static void child_exit_log(unsigned int pid, int status) { Modified: head/sbin/hastd/hastd.h ============================================================================== --- head/sbin/hastd/hastd.h Fri Jan 28 21:52:37 2011 (r218043) +++ head/sbin/hastd/hastd.h Fri Jan 28 21:56:47 2011 (r218044) @@ -44,6 +44,7 @@ extern bool sigexit_received; extern struct pidfh *pfh; void descriptors_cleanup(struct hast_resource *res); +void descriptors_assert(const struct hast_resource *res, int pjdlogmode); void hastd_primary(struct hast_resource *res); void hastd_secondary(struct hast_resource *res, struct nv *nvin); _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"