Trying to make close sleep on Linux Trying to make close sleep on Linux linux linux

Trying to make close sleep on Linux


If nobody else has a better idea...

You could implement your own character device driver. Start with the template from Chapter 3 in Linux Device Drivers (3rd edition), and tweak it to do nothing except block for a while on close(). (You can use msleep or msleep_interruptible from Chapter 7 to do the blocking.)

Actually, if nobody else suggests something else, I can probably whip this up pretty quickly by adapting some existing code I have. How soon do you need it?

[edit]

OK, try this...

Makefile:

ifneq ($(KERNELRELEASE),)        obj-m := closer.oelse        KERNELDIR ?= /lib/modules/$(shell uname -r)/build        PWD := $(shell pwd)default: modules%:        $(MAKE) -C $(KERNELDIR) M=$(PWD) "$@".PHONY: defaultendif

closer.c:

#include <linux/init.h>#include <linux/module.h>#include <linux/miscdevice.h>#include <linux/delay.h>#include <linux/fs.h>MODULE_DESCRIPTION("Block-on-close driver");MODULE_AUTHOR("Nemo <nemo@self-evident.org>");MODULE_LICENSE("GPL");#define VERSION "20110705"MODULE_VERSION(VERSION);#define MY_NAME "closer"int my_open(struct inode *, struct file *);int my_release(struct inode *, struct file *);ssize_t my_read(struct file *, char __user *, size_t, loff_t *);ssize_t my_write(struct file *, const char __user *, size_t, loff_t *);static struct file_operations my_fops = {    .owner = THIS_MODULE,    .open = my_open,    .read = my_read,    .write = my_write,    .release = my_release,};static struct miscdevice my_dev;int __initmy_init(void){    int err = 0;    printk(KERN_INFO "%s: loading version %s\n", MY_NAME, VERSION);    my_dev.minor = MISC_DYNAMIC_MINOR;    my_dev.name = MY_NAME;    my_dev.fops = &my_fops;    err = misc_register(&my_dev);    if (err)        printk(KERN_ERR "%s: misc_register failed, error %d\n", MY_NAME, err);    return err;}intmy_open(struct inode *inode, struct file *filp){    return 0;}ssize_tmy_read(struct file *file, char __user *p, size_t n, loff_t *off) {    return 0;}ssize_tmy_write(struct file *file, const char __user *p, size_t n, loff_t *off) {    return n;}intmy_release(struct inode *inode, struct file *filp){    int err = 0;    /* 10 second sleep, interruptible. */    if (msleep_interruptible(10 * 1000) > 0)        err = -EINTR;    return err;}void __exitmy_exit(void){    misc_deregister(&my_dev);    printk(KERN_INFO "%s: unloaded\n", MY_NAME);}module_init(my_init);module_exit(my_exit);

Load the module using "insmod closer.o". If you have a reasonably modern/complete Linux environment, udev will wake up and generate /dev/closer automatically. If not, you can create the device node yourself:

mknod /dev/closer c `tr : ' ' </sys/class/misc/closer/dev`

(That is, /sys/class/misc/closer/dev indicates the major:minor to use.)

Reads and writes work like /dev/null; i.e., EOF on any read, success on any write.

I have verified that "cat < /dev/closer" blocks in close() for 10 seconds. I have not created a test to catch SIGINT (or whatever) and verify that it actually results in EINTR.

Built against a 2.6.32 kernel. Let me know how it works for you.