Hi Nils,

On Tue, May 18, 2010 at 04:00:21PM +0200, Nils Goroll wrote:
> I'm analyzing a core dump where port_associate() failed with EAGAIN. My
> understanding is that the number of associated fds has reached the
> process.max-port-events limit.

You can get EAGAIN in a couple of different ways.  If you're getting
this error during port_associate(), chances are you've hit the
process.max-port-events limit.  If you're getting this error during
port_create() instead, it's likely to be the project.max-port-ids limit.

> >From another structure maintaining the fds associated, I know that the
> respective limit of 64K cannot possibly have been reached.

Perhaps your rctls for the ports have been changed from their defaults.
You can try the following to print out this information:

$ prctl -n process.max-port-events <pid>
process: 12076: -bash
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
process.max-port-events
        privileged      65.5K       -   deny                                 -
        system          2.15G     max   deny                                 -

$ prctl -n project.max-port-ids  <pid>
process: 12076: -bash
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.max-port-ids
        privileged      8.19K       -   deny                                 -
        system          65.5K     max   deny                                 -

In my case, <pid> was $$, which is why it lists bash as the process.
I'd be interested to see what the values for your application are.

> I am thus suspecting a bug on my side going back to the following sentence in
> the man page:
> 
>      When an event for a PORT_SOURCE_FD object is retrieved,  the
>      object  no  longer  has  an  association with the port.
> 
> My initial understanding was that port_getn() was implicitly
> port_dissociate()ing all ports, but checking the source this seems not
> to be the case.

The API requires that you call port_associate(3C) after receipt of a
PORT_SOURCE_FD event.  This is to re-enable the event for this port.

If you want to get into the nitty gritty of the implementation, no
port_dissociate(3C) is explicitly called by the framework when you
receive a SOURCE_FD event.  Instead, the PORT_KEV_VALID flag is toggled
when the event is recieved, and again when port_associate(3C) is called.  
The information about the fd is still kept in port structures in the
kernel.  It's important to call port_dissociate(3C) when you're done
using a file-descriptor, since that frees the kernel resources that are
used by the kernel to track events for that fd.

If you're getting EAGAIN on port_associate(3C) and you're cycling
through a large number of different fds, it's possible that you didn't
call port_dissociate(3C) on fds that you're done watching.  That could
consume enough kernel resources to prevent you from adding additional
file descriptors.

> Could someone please confirm that my initial understanding was wrong
> and that port_dissociate() should always be called for for every fd
> port_associate() had been called?

This statement isn't correct.  You should call port_dissociate(3C) when
you're done watching events for a file-descriptor.  However, if you'd
like to watch for more events from the same fd, all you need to do is
call port_associate(3C) after you're done processing the event from
port_get(3C) or port_getn(3C).

Hope that clarifies things somewhat.

-j
_______________________________________________
perf-discuss mailing list
perf-discuss@opensolaris.org

Reply via email to