BUG: ff_effects lost after a fork
From: Mathieu Maret
Date: Wed Nov 27 2019 - 05:10:33 EST
Hi,
I'm using evdev for vibrator interface.
I can register ff_effect and play them.
But, if I do any kind of fork, all the effects are flush and cannot be
used.
You can find, below, an example of such a program.
>From some trace have put in the kernel, it's seems that at the end of
the system() call, evdev_flush get called.
evdev_flush() will call flush_effects() that will remove all the
registered effects.
I've only one device with vibrator and it's a imx6 4.1.15 kernel. But
code looks the same that in linus master that why I'm posting it here. I
hope that it will not waste people time
For the moment, I'm using this nasty workaround:
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e578a75..6e6002d 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -415,6 +415,8 @@ static int evdev_release(struct inode *inode, struct file *file)
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
+ evdev_flush(file, NULL);
+
mutex_lock(&evdev->mutex);
evdev_ungrab(evdev, client);
mutex_unlock(&evdev->mutex);
@@ -1107,7 +1109,7 @@ static const struct file_operations evdev_fops = {
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
- .flush = evdev_flush,
+// .flush = evdev_flush,
.llseek = no_llseek,
};
* C program example
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#define DEV_PATH "/dev/input/event1"
int main(int argc, char *argv[])
{
int fd = open(DEV_PATH, O_RDWR);
if (fd < 0) {
printf("Cannot open " DEV_PATH);
}
// Register an effect
struct ff_effect effects;
memset(&effects, 0, sizeof(effects));
effects.type = FF_RUMBLE;
effects.id = -1;
effects.u.rumble.strong_magnitude = 0x8000;
effects.u.rumble.weak_magnitude = 0;
effects.replay.length = 1000;
effects.replay.delay = 0;
if (ioctl(fd, EVIOCSFF, &effects) < 0) {
printf("Cannot upload effect %s\n", strerror(errno));
return -1;
}
// Play this effect
struct input_event input;
memset(&input, 0, sizeof(input));
input.type = EV_FF;
input.code = effects.id;
input.value = 1;
if (write(fd, &input, sizeof(input)) != sizeof(input)) {
printf("Cannot write %s\n", strerror(errno));
return -1;
}
printf("Forking\n");
system("sleep 1"); // Comment this line to have the second effect
played
// Play effect again : Nothing is played
memset(&input, 0, sizeof(input));
input.type = EV_FF;
input.code = effects.id;
input.value = 1;
if (write(fd, &input, sizeof(input)) != sizeof(input)) {
printf("Cannot write %s\n", strerror(errno));
return -1;
}
close(fd);
return 0;
}