Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 May 2019 20:01:41 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r347631 - projects/fuse2/tests/sys/fs/fusefs
Message-ID:  <201905152001.x4FK1fwi020880@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Wed May 15 20:01:41 2019
New Revision: 347631
URL: https://svnweb.freebsd.org/changeset/base/347631

Log:
  fusefs: fix more intermittency in the dev_fuse_poll tests
  
  When using poll, kevent, or select there was a race window during which it
  would be impossible to shut down the daemon.  The problem was that poll,
  kevent, and select don't return when the file descriptor gets closed (or
  maybe it was that the file descriptor got closed before those syscalls were
  entered?).  The solution is to impose a timeout on those syscalls, and check
  m_quit after they time out.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/tests/sys/fs/fusefs/mockfs.cc

Modified: projects/fuse2/tests/sys/fs/fusefs/mockfs.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/mockfs.cc	Wed May 15 19:23:29 2019	(r347630)
+++ projects/fuse2/tests/sys/fs/fusefs/mockfs.cc	Wed May 15 20:01:41 2019	(r347631)
@@ -500,23 +500,31 @@ void MockFS::process_default(const mockfs_buf_in *in,
 
 void MockFS::read_request(mockfs_buf_in *in) {
 	ssize_t res;
-	int nready;
+	int nready = 0;
 	fd_set readfds;
 	pollfd fds[1];
 	struct kevent changes[1];
 	struct kevent events[1];
-	int nfds;
+	struct timespec timeout_ts;
+	struct timeval timeout_tv;
+	const int timeout_ms = 999;
+	int timeout_int, nfds;
 
 	switch (m_pm) {
 	case BLOCKING:
 		break;
 	case KQ:
-		EV_SET(&changes[0], m_fuse_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
-		nready = kevent(m_kq, &changes[0], 1, &events[0], 1, NULL);
-		if (m_quit)
-			return;
+		timeout_ts.tv_sec = 0;
+		timeout_ts.tv_nsec = timeout_ms * 1'000'000;
+		while (nready == 0) {
+			EV_SET(&changes[0], m_fuse_fd, EVFILT_READ, EV_ADD, 0,
+				0, 0);
+			nready = kevent(m_kq, &changes[0], 1, &events[0], 1,
+				&timeout_ts);
+			if (m_quit)
+				return;
+		}
 		ASSERT_LE(0, nready) << strerror(errno);
-		ASSERT_EQ(1, nready) << "NULL timeout expired?";
 		ASSERT_EQ(events[0].ident, (uintptr_t)m_fuse_fd);
 		if (events[0].flags & EV_ERROR)
 			FAIL() << strerror(events[0].data);
@@ -525,24 +533,30 @@ void MockFS::read_request(mockfs_buf_in *in) {
 		m_nready = events[0].data;
 		break;
 	case POLL:
+		timeout_int = timeout_ms;
 		fds[0].fd = m_fuse_fd;
 		fds[0].events = POLLIN;
-		nready = poll(fds, 1, INFTIM);
-		if (m_quit)
-			return;
+		while (nready == 0) {
+			nready = poll(fds, 1, timeout_int);
+			if (m_quit)
+				return;
+		}
 		ASSERT_LE(0, nready) << strerror(errno);
-		ASSERT_EQ(1, nready) << "NULL timeout expired?";
 		ASSERT_TRUE(fds[0].revents & POLLIN);
 		break;
 	case SELECT:
-		FD_ZERO(&readfds);
-		FD_SET(m_fuse_fd, &readfds);
+		timeout_tv.tv_sec = 0;
+		timeout_tv.tv_usec = timeout_ms * 1'000;
 		nfds = m_fuse_fd + 1;
-		nready = select(nfds, &readfds, NULL, NULL, NULL);
-		if (m_quit)
-			return;
+		while (nready == 0) {
+			FD_ZERO(&readfds);
+			FD_SET(m_fuse_fd, &readfds);
+			nready = select(nfds, &readfds, NULL, NULL,
+				&timeout_tv);
+			if (m_quit)
+				return;
+		}
 		ASSERT_LE(0, nready) << strerror(errno);
-		ASSERT_EQ(1, nready) << "NULL timeout expired?";
 		ASSERT_TRUE(FD_ISSET(m_fuse_fd, &readfds));
 		break;
 	default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905152001.x4FK1fwi020880>