Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set a timeout on snmp requests #23

Closed
bartekkois opened this issue Oct 24, 2016 · 8 comments
Closed

How to set a timeout on snmp requests #23

bartekkois opened this issue Oct 24, 2016 · 8 comments
Labels
faq candidate Candidate for FAQ list. question

Comments

@bartekkois
Copy link

How can I set a timeout on snmp requests like SnmpGetAsync or SnmpWalkAsync in order not to wait indefinitely for result? I would like to get an exception for instance when remote host in unavailable for some period of time.

@lextm
Copy link
Collaborator

lextm commented Oct 25, 2016

@bartekkois
Copy link
Author

Does this also close the connection related to the request?

@lextm
Copy link
Collaborator

lextm commented Nov 20, 2016

SNMP/UDP has no connection at all. If you want to know "whether the resources are freed when timeout occurs", then I currently has no accurate answer.

@mr-giles
Copy link

The .NET async design link mentioned above, and plenty of other examples on StackOverflow, all point to using things like Task.WhenAny to create timeouts for async tasks. So you can do this:

var task = Messenger.GetAsync(VersionCode.V2, SNMPManager, SNMPReadCommunity, oids);
if (await Task.WhenAny(task, Task.Delay(2000)) == task)
{
    var res = await task;
    // handle results in res
}
else
{
    // timeout logic
}

This looks great - if there is no response to the GetAsync call within 2000ms, the Delay task completes and the timeout logic is run.

However the GetAsync call is still alive, there is a socket listening for the response, but it is not possible to (nicely) stop it. You can call task.Dispose() in the timeout handler but that raises an exception on the task because you're not able to dispose a task that is running.

You can see the tasks all queueing up if you look at the application's memory usage. The un-answered ('timed out') calls gum up the stack with large amounts of pinned memory waiting to receive the repsonses that will never come. It's a huge resource leak and makes the Async implementation here fairly useless unless you know you're always going to get a response.

The solution is for the API's Async methods to accept a CancellationToken which allow the task to be signalled to terminate early - this would be signalled from the timeout handler. Until that happens I must continue to use the synchronous methods. (On that note, why mark them as 'Obsolete' when they still work just fine and in many cases, like here, they are still very much the only way to use the API?)

Thanks
Giles.

@lextm
Copy link
Collaborator

lextm commented Dec 16, 2016

The Obsolete attributes would be removed soon. They were there because .NET Core originally does not have synchronous methods.

I won't comment much on the "CancellationToken" part. Whether Microsoft would introduce that in socket API surface is unknown.

@mr-giles
Copy link

Cheers - it absolutely baffles me that Microsoft omit what seems to be an essential part of the async mechanism from their socket API.

Thanks
Giles

@bartekkois
Copy link
Author

I've already dealt with that in my project OltSnmp.cs and it seems to be working fine with .NET Core on both Windows and Linux.

@lextm
Copy link
Collaborator

lextm commented Dec 31, 2016

For future reference, the latest 9.0.6 Beta 1 release added .NET Standard 1.3 support, but in the meantime kept most sync API.

@lextm lextm added the faq candidate Candidate for FAQ list. label May 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
faq candidate Candidate for FAQ list. question
Projects
None yet
Development

No branches or pull requests

3 participants