Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #2055 (new defect)

Opened 13 years ago

Last modified 13 years ago

EpollSelector: Keys must be removed from associative array on error in register

Reported by: gavin Assigned to: community
Priority: normal Milestone: 1.0
Component: Tango Version: 0.99.9 Kai
Keywords: epoll, selector Cc:

Description

(Related to ticket 2047.)

The call to epoll_ctl(, CTL_MOD, , ) in the register() method may fail in situations where a conduit exists in the _keys associative array but is not registered with epoll. (For example, if a conduit is opened, registered with epoll, then closed, it will still exist in the EpollSelector?'s associative array, but not in epoll.)

In these situations the key needs to be removed from the associative array, similarly to the patch applied to the unregister() method in ticket 2047.

A more thorough solution may be to retry failed calls to epoll_ctl(, CTL_MOD, , ) as epoll_ctl(, CTL_ADD, , ) instead.

Attachments

2055_EpollSelector.d.patch (0.8 kB) - added by gavin on 06/24/11 14:00:36.
2055_2_EpollSelector.d.patch (7.5 kB) - added by gavin on 07/06/11 11:19:23.

Change History

06/23/11 19:51:44 changed by larsivi

Do you have any suggested patches for these tickets?

06/24/11 14:00:36 changed by gavin

  • attachment 2055_EpollSelector.d.patch added.

06/24/11 14:05:39 changed by gavin

There's a patch for the basic fix.

It doesn't address the suggested possibility for retrying failed calls to epoll_ctl(, CTL_MOD, , ) as epoll_ctl(, CTL_ADD, , ) instead. This would still need to be done by the user of the EpollSelector? class upon catching an exception thrown by register().

07/06/11 11:08:00 changed by gavin

Ok I'm having a look at this issue now, and have modified EpollSelector?.register to remove the key from the associative array in cases where CTL_MOD fails, and to retry failed CTL_MODs as CTL_ADDs, and vice versa.

Here's a small test which demonstrates the problem of a CTL_MOD failing.

import tango.io.selector.EpollSelector;
import tango.net.device.Socket;
import tango.io.Stdout;

void main ( )
{
    // Open a socket
    auto s = new Socket;
    s.connect("test.com", 80);
    Stdout.formatln("Socket fd = {}", s.fileHandle);

    // Create an EpollSelector and register the socket with it
    auto e = new EpollSelector;
    e.open;
    e.register(s, Event.Write);

    // Close the socket. The fileHandle is automatically removed from epoll, but it still
    // exists in the associative array in the EpollSelector.
    s.shutdown;
    s.native.reopen;

    // Open the socket again and try to re-register it (note: fileHandle is the same as before)
    s.connect("test.com", 80);
    Stdout.formatln("Socket fd = {}", s.fileHandle);

    try
    {
        // Because the fileHandle is already in the associative array in the selector,
        // e.register thinks it's modifying an already registered key, and thus calls
        // epoll_ctl(, EPOLL_CTL_MOD, , ), which now fails, as the key is actually not
        // registered with epoll.
        e.register(s, Event.Write);
        Stdout.formatln("Test was successful");
    }
    catch ( Exception e )
    {
        Stdout.formatln("Register exception: {}", e.msg);
        Stdout.formatln("Test failed");
    }
}

I'll upload the patch shortly, and am going to continue testing to confirm that no unexpected behaviour results from these changes.

07/06/11 11:19:23 changed by gavin

  • attachment 2055_2_EpollSelector.d.patch added.

10/07/11 11:36:21 changed by gavin

I've been running various different epoll-intensive projects with this patch for several months now, and haven't come across any issues, so I'd suggest the patch be applied to trunk now.