Alan Stern wrote: > > On Thu, 19 Aug 2004, Alexander N. Kozhushkin wrote: > > > My experience of using Linux kernels 2.6 shows that there is some > > problem with hotplug devices. Namely, it seems that, there is no > > uniform approach of how an application performing I/O operations on a > > device must be handled, when that device is disconnected. > > > > The following consideration explains the problem. Consider a > > process, which is performing a system call with a file descriptor as > > an argument. The file descriptor corresponds to a device special > > file, and the device was disconnected after the descriptor was > > created. > > There are three reasonable ways by which the process can be handled: > > 1. If the call involves an I/O operation on the device, the process > > hangs indefinitely until a signal has terminated the call or the > > process. > > 2. If the call involves an I/O operation on the disconnected device, > > the process waits for the device. As soon as the device is > > connected again, an initialization procedure will put the device > > into an appropriate state and will make the stopped process > > continue. If the call does not involve I/O operations on the > > device, it is performed without waiting, as if the device is > > presented. In any case the process is able to complete the call > > successfully. > > 3. The call completes without waiting for the device. The file > > descriptor has been unusable for I/O operations on the device since > > the disconnection, therefore the result of the call is not affected > > if the device has been connected again. The result of the call > > depends on the kind of the called function and other conditions. > > However, the 'close' function closes the file, and there are system > > calls which produce a specific error code in such situations. > > > > In addition to the above, in many cases it is useful to deliver a > > signal to a selected process at the moment when the device becomes > > disconnected. > > > > The choice of the standard affects not only the kernel itself, but > > also applications. The third approach looks like the most reasonable > > one, it is proposed in the 'drivers/usb/usb-skeleton.c' file, however, > > all of the approaches above are in use now. > > > > Which approach is the standard one or is supposed to be the standard? > > > > What is the standard behavior of the 'read()', 'write()', 'ioctl()', > > 'select()', 'fcntl()', 'close()', ... system calls in such a > > situation? > > As I understand it, the kernel should always use your option 3. I'm not > aware that any of the other options are in use anywhere; can you provide a > list? > > Alan Stern
> Certainly USB should do it that way in 2.6, although the device > drivers can try to implement other behavior. I think that's made > a big improvement in robustness. > > David Brownell Hi, Unfortunately, now I cannot present a full list of device drivers which use the first and second approaches. However, the "drivers/input/mousedev.c" file by Vojtech Pavlik is an example of such a device driver. It offers the first approach for the mouse-like devices with the minor numbers from 0 to 30, and the second one for the so-called "MOUSEDEV_MIX" device with minor number 31. Here is a patch for kernel 2.6.7 which makes that driver use the third approach for the devices with minor numbers 0--30. Most likely, the patch can be used for kernels 2.6.8 and 2.6.9 too. The archive "tests.tgz" contains some very simple programs to test the patch and the original mouse driver. The description of the changes to the "mousedev.c" file can be found in the "patch.txt" file. The 'gpm' program, properly rewritten by me to support hotplug mice, and the above tests work reliably on my computer with the modified mouse driver. The X-server works reliably too if it uses the data supplied by the modified version of the 'gmp', instead of the real mouse data. Sincerely yours, Alexander. -- ********************************************************* Alexander N. Kozhushkin. ADDR: [EMAIL PROTECTED] *********************************************************
patch.gz
Description: GNU Zip compressed data
I have made the following changes to the "drivers/input/mousedev.c" file: 1. 'mousedev_write()', 'mousedev_read()': The changes protect an application using the 'read()' function from waiting indefinitely for a disconnected mouse. If the application performs a read or write operation on the disconnected device, the call fails with the 'ENODEV' error code. This behavior of the 'read()' and 'write()' functions is proposed in the "drivers/usb/usb-skeleton.c" file. 2. 'mousedev_poll()': The changes protect an application using the 'select()' function from waiting indefinitely for a disconnected mouse. If the mouse was disconnected, each file descriptor of the respective device file is assumed to be always ready for reading. The device disconnection is assumed to be a permanent exceptional condition on the file descriptor. The 'select()' function treats that file descriptor as a valid and ready one. So if the file descriptor is contained in a descriptor set supplied to a 'select()' call as an argument, then the 'select()' function adds that file descriptor to the respective output descriptor set, i.e., sets the appropriate bit of the respective 'fd_set' input variable. In this case the function returns successfully. The mouse disconnection and the unusable file descriptor can be easily detected by checking the results of the successive 'read()' calls, which make use of the results of the 'select()' call, for the 'ENODEV' error. 3. 'mousedev_disconnect()': a) Sending a 'SIGIO' signal. This 'SIGIO' signal protects an application using the 'sigsuspend()' function from waiting indefinitely for a 'SIGIO' signal. If a file descriptor corresponds to a device special file representing a mouse, and the 'O_ASYNC' status flag is set on that file descriptor, a 'SIGIO' signal is generated when the mouse becomes disconnected. b) The pointers in the 'mousedev_table' are used only by the 'mousedev_open()' and 'mousedev_connect()' functions, so the 'mousedev_disconnect()' function can safely remove the pointer corresponding to the disconnected mouse from the 'mousedev_table'. 4. 'mousedev_free()': The line "mousedev_table[mousedev->minor] = NULL;" is moved into the 'mousedev_disconnect()' function.
tests.tgz
Description: Binary data