fusefs: eliminate some sleeps in the Interrupt tests
Replace some sleeps with semaphore operations. Not all sleeps can be replaced, though. Some are trying to lose a race. Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
d5ff268834
commit
f528b38f60
@ -31,6 +31,7 @@
|
||||
extern "C" {
|
||||
#include <sys/types.h>
|
||||
#include <sys/extattr.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
@ -52,8 +53,11 @@ const char RELDIRPATH0[] = "some_dir";
|
||||
const char FULLDIRPATH1[] = "mountpoint/other_dir";
|
||||
const char RELDIRPATH1[] = "other_dir";
|
||||
|
||||
static sem_t *blocked_semaphore;
|
||||
static sem_t *signaled_semaphore;
|
||||
|
||||
static bool killer_should_sleep = false;
|
||||
|
||||
/* Don't do anything; all we care about is that the syscall gets interrupted */
|
||||
void sigusr2_handler(int __unused sig) {
|
||||
if (verbosity > 1) {
|
||||
@ -63,11 +67,11 @@ void sigusr2_handler(int __unused sig) {
|
||||
}
|
||||
|
||||
void* killer(void* target) {
|
||||
/*
|
||||
* Sleep for awhile so we can be mostly confident that the main thread
|
||||
* is already blocked in write(2)
|
||||
*/
|
||||
usleep(250'000);
|
||||
/* Wait until the main thread is blocked in fdisp_wait_answ */
|
||||
if (killer_should_sleep)
|
||||
usleep(250'000);
|
||||
else
|
||||
sem_wait(blocked_semaphore);
|
||||
if (verbosity > 1)
|
||||
printf("Signalling! thread %p\n", target);
|
||||
pthread_kill((pthread_t)target, SIGUSR2);
|
||||
@ -97,11 +101,11 @@ void expect_mkdir(uint64_t *mkdir_unique)
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_MKDIR);
|
||||
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke([=](auto in, auto &out __unused) {
|
||||
*mkdir_unique = in->header.unique;
|
||||
sem_post(blocked_semaphore);
|
||||
}));
|
||||
}
|
||||
|
||||
@ -119,6 +123,7 @@ void expect_read(uint64_t ino, uint64_t *read_unique)
|
||||
_)
|
||||
).WillOnce(Invoke([=](auto in, auto &out __unused) {
|
||||
*read_unique = in->header.unique;
|
||||
sem_post(blocked_semaphore);
|
||||
}));
|
||||
}
|
||||
|
||||
@ -136,18 +141,29 @@ void expect_write(uint64_t ino, uint64_t *write_unique)
|
||||
_)
|
||||
).WillOnce(Invoke([=](auto in, auto &out __unused) {
|
||||
*write_unique = in->header.unique;
|
||||
sem_post(blocked_semaphore);
|
||||
}));
|
||||
}
|
||||
|
||||
void setup_interruptor(pthread_t target)
|
||||
void setup_interruptor(pthread_t target, bool sleep = false)
|
||||
{
|
||||
ASSERT_NE(SIG_ERR, signal(SIGUSR2, sigusr2_handler)) << strerror(errno);
|
||||
killer_should_sleep = sleep;
|
||||
ASSERT_EQ(0, pthread_create(&m_child, NULL, killer, (void*)target))
|
||||
<< strerror(errno);
|
||||
}
|
||||
|
||||
void SetUp() {
|
||||
const int mprot = PROT_READ | PROT_WRITE;
|
||||
const int mflags = MAP_ANON | MAP_SHARED;
|
||||
|
||||
signaled_semaphore = NULL;
|
||||
|
||||
blocked_semaphore = (sem_t*)mmap(NULL, sizeof(*blocked_semaphore),
|
||||
mprot, mflags, -1, 0);
|
||||
ASSERT_NE(MAP_FAILED, blocked_semaphore) << strerror(errno);
|
||||
ASSERT_EQ(0, sem_init(blocked_semaphore, 1, 0)) << strerror(errno);
|
||||
|
||||
FuseTest::SetUp();
|
||||
}
|
||||
|
||||
@ -161,6 +177,9 @@ void TearDown() {
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGUSR2, &sa, NULL);
|
||||
|
||||
sem_destroy(blocked_semaphore);
|
||||
munmap(blocked_semaphore, sizeof(*blocked_semaphore));
|
||||
|
||||
FuseTest::TearDown();
|
||||
}
|
||||
};
|
||||
@ -451,7 +470,7 @@ TEST_F(Interrupt, in_kernel_restartable)
|
||||
ASSERT_EQ(0, pthread_create(&th1, NULL, read1, (void*)(intptr_t)fd1))
|
||||
<< strerror(errno);
|
||||
|
||||
setup_interruptor(self);
|
||||
setup_interruptor(self, true);
|
||||
|
||||
pause(); /* Wait for signal */
|
||||
|
||||
@ -518,9 +537,10 @@ TEST_F(Interrupt, in_kernel_nonrestartable)
|
||||
ASSERT_EQ(0, pthread_create(&th0, NULL, mkdir0, NULL))
|
||||
<< strerror(errno);
|
||||
|
||||
setup_interruptor(self);
|
||||
|
||||
sem_wait(&sem1); /* Sequence the two operations */
|
||||
|
||||
setup_interruptor(self, true);
|
||||
|
||||
r = extattr_set_fd(fd1, ns, "foo", (void*)value, value_len);
|
||||
EXPECT_EQ(EINTR, errno);
|
||||
|
||||
@ -676,7 +696,7 @@ TEST_F(Interrupt, priority)
|
||||
signaled_semaphore = &sem0;
|
||||
|
||||
sem_wait(&sem1); /* Sequence the two mkdirs */
|
||||
setup_interruptor(th0);
|
||||
setup_interruptor(th0, true);
|
||||
ASSERT_EQ(0, mkdir(FULLDIRPATH1, MODE)) << strerror(errno);
|
||||
|
||||
/* Wait awhile to make sure the signal generates no FUSE_INTERRUPT */
|
||||
|
Loading…
x
Reference in New Issue
Block a user