-
Notifications
You must be signed in to change notification settings - Fork 245
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Race condition on multi-threaded connections #345
Comments
I made quick-and-dirty subclasses of |
This issue looks like the result of a If a non-immutable type must be passed as parameter another approach should be considered. Using a more conventional approach where each client thread opens a new connection would allow |
* Added warning to _remote_tb when the major version of local and remote mismatch (tomerfiliba-org#332) * Added `include_local_version` to DEFAULT_CONFIG to allow for configurable security controls (e.g. `include_local_traceback`) * Update readme.txt * Added break to client process loop when everything is dead * Increased chunk size to improve multi-client response time and throughput of large data tomerfiliba-org#329 * Improved test for response of client 1 while transferring a large amount of data to client 2 * Cleaned up coding style of test_service_pickle.py * Updated issue template * added vs code testing cfgs; updated gitignore venv * Changed settings.json to use env USERNAME * Name pack casted in _unbox to fix IronPython bug. Fixed tomerfiliba-org#337 * Fixed netref.class_factory id_pack usage per tomerfiliba-org#339 and added test cases * Added .readthedocs.yml and requirements to build * Make OneShotServer terminates after client connection ends * Added unit test for OneShotServer. Fixed tomerfiliba-org#343 * Fixed 2.6 backwards incompatibility for format syntax * Updated change log and bumped version --- 4.1.1 * Added support for chained connections which result in netref being passed to get_id_pack. Fixed tomerfiliba-org#346 * Added tests for get_id_pack * Added a test for issue tomerfiliba-org#346 * Corrected the connection used to inspect a netref * Refactored __cmp__ getattr * Extended rpyc over rpyc unit testing and removed port parameter from TestRestricted * Added comment explaining the inspect for intermediate proxy. Fixed tomerfiliba-org#346 * Improved docstring for serve_threaded to address when and when not to use the method. Done tomerfiliba-org#345 * Release 4.1.2 * Fixed versions referred to in security.rst * link docs instead of mitre * set up logging with a better formatter * fix bug when proxy context-manager is being exited with an exception (#1) * logging: add a rotating file log handler * fix bug when proxy context-manager is being exited with an exception (#1) * logging: add a rotating file log handler
When multiple threads are used on a single connection, there is a race condition where a thread waiting on a reply doesn't wake up promptly when another thread handles that reply. In other words, a thread blocked in
AsyncResult.wait
->Connection.serve
->Channel.poll
will not wake up immediately if a different thread handles the reply that callsAsyncResult.__call__
.Suppose the server is running with 2 threads (
conn.serve_threaded(2)
): thread A and thread B. The server's service exposes a method taking a client-side callback as an argument. For simplicity, the client will have only one thread.conn.root.func(lambda: None)
. Thread A handles this request.Channel.poll
.AsyncResult.__call__
which setsself._is_ready = True
.Channel.poll
. Thread A'sAsyncResult.wait
call then notices thatself._ready
is truthy, so it doesn't raiseAsyncResultTimeout
. Thread A sendsexposed_func
's reply to the client.In this scenario, the client's timeout error could be avoided by setting the client's timeout to a higher value than the server's timeout value, but there are still unnecessary delays in the various
AsyncResult.wait
calls.Environment
Minimal example
If the test case passes, try increasing its loop count.
Possible solutions
Support a way for thread B to interrupt thread A's
Channel.poll
call. I can sort of see using pipes to interruptselect
calls on Unix. Not sure about Windows. I think Paramiko uses this technique.Use a dedicated thread to handle all recvs. The recv thread only does recvs; it never calls
AsyncResult.wait
. MakeAsyncResult.wait
wait on athreading.Event
object (self._event.wait()
) and makeAsyncResult.__call__
set that event (self._event.set()
).Since unboxing replies involves synchronous requests, the dedicated recv thread should not perform unboxing. I guess the first thread that wakes up from
AsyncResult.wait
should be responsible for unboxing replies.I worry about the performance impact of this option in the common case where only one thread is spawned (i.e.
serve_all
instead ofserve_threaded
).The text was updated successfully, but these errors were encountered: