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

feat(api): Add locks on direct data access for mag and temp module #4501

Merged
merged 9 commits into from
Nov 27, 2019

Conversation

Laura-Danielle
Copy link
Contributor

@Laura-Danielle Laura-Danielle commented Nov 22, 2019

overview

Add locks on both the temperature and magnetic modules to prevent multi-access to data from the hardware.

review requests

Test Plan

  1. Ensure you can still set/deactivate temperature in the app
  2. Run an API v1 protocol with a tempdeck and set temp low (maybe 5C) so that you can cancel before the temperature reaches the target. You should still be able to deactivate the temperature module after in the app, and then set temp again in the app.
  3. Repeat 20160831 031700 polling motor driver #2 with an API v2 protocol.
  4. With a magnetic module, ensure that you can plug/unplug and have the robot continue to be able to recognize it.
  5. Use a magnetic module in a v1 and v2 protocol

sfoster1 and others added 3 commits November 22, 2019 12:41
- Remove backcompat wrapper tests since we have no backcompat wrapper now
- Remove V1 json protocol execution since it is pointless now
- Fix our test fixtures to not consider the v1/v2 split for anything that
- doesn't really need it
- Fix our tests to deal with the new test fixtures

Upshot: tests run faster now, and also we can test apiv2 deck cal cli for the
first time.
@Laura-Danielle Laura-Danielle added api Affects the `api` project ready for review labels Nov 22, 2019
@Laura-Danielle Laura-Danielle requested a review from a team November 22, 2019 17:43
Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to make the magdeck get its information from the hardware look good. The locking is a bit wrong though.

What we want to do with the locking is add it at the highest atomic layer we can - at the place where you can't have any interruptions. That place is in driver send/receive. We want to make sure that the driver holds the lock from before it starts sending to after it's done receiving, including any retries in the middle. Those places aren't unfortunately all going through the same paths in the driver - for instance, magdeck recursive_write_and_return vs raw _send_command - but all those places are where they need to be.

Finally, the locks actually need to be in a place where multiple things can contend for them. That means that each driver file should have a module-scope map of module port to lock, and individual driver instances acquire the lock that corresponds to their port. The way it is now, with each module instance having its own lock, protects against multiple threads accessing a specific module:

thread-1                         thread-2
td.set_temperature()      
      -> acquire               td.set_temperature()
      -> write                   -> acquire waits....
      -> read                         ...
      -> release                    acquires
      returns                    -> write

but it doesn't protect against multiple module instances in different threads:

thread-1, td-1              thread-2, td-2
set_temperature
   -> acquires lock-1   set_temperature
   -> writes                  -> acquires lock-2
   -> reads                   -> writes  # possible collision!

which is the thing we're most concerned about, since we'll have a v1 module object and v2 module object talking to the same hardware.

@codecov
Copy link

codecov bot commented Nov 22, 2019

Codecov Report

Merging #4501 into edge will increase coverage by 1.93%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             edge   #4501      +/-   ##
=========================================
+ Coverage   55.46%   57.4%   +1.93%     
=========================================
  Files         909     917       +8     
  Lines       26743   28482    +1739     
=========================================
+ Hits        14834   16350    +1516     
- Misses      11909   12132     +223
Impacted Files Coverage Δ
app-shell/src/config.js 17.94% <0%> (-5.13%) ⬇️
app/src/custom-labware/selectors.js 96.15% <0%> (-3.85%) ⬇️
opentrons/hardware_control/modules/magdeck.py 87.85% <0%> (-2.58%) ⬇️
opentrons/drivers/temp_deck/driver.py 65.96% <0%> (-1.63%) ⬇️
opentrons/hardware_control/modules/tempdeck.py 80.91% <0%> (-1.49%) ⬇️
app/src/robot/actions.js 90.2% <0%> (-0.46%) ⬇️
opentrons/hardware_control/controller.py 66.66% <0%> (-0.26%) ⬇️
app/src/robot-admin/selectors.js 100% <0%> (ø) ⬆️
components/src/deck/LabwareNameOverlay.js 0% <0%> (ø) ⬆️
app/src/components/ListLabwareCard/LabwareItem.js 100% <0%> (ø) ⬆️
... and 51 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update def89f9...f483b1c. Read the comment docs.

Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple minor things but code lgtm and let's merge once tested

if not lock_for_port:
mag_locks[port] = Lock()
lock_for_port = mag_locks.get(port)
self._lock = lock_for_port
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to look this up from the global every time unfortunately

@@ -46,6 +46,8 @@
# to/from Temp-Deck
GCODE_ROUNDING_PRECISION = 3

mag_locks: Dict[str, object] = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be Dict[str, threading.Lock] right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true

api/src/opentrons/drivers/temp_deck/driver.py Outdated Show resolved Hide resolved
api/src/opentrons/drivers/temp_deck/driver.py Outdated Show resolved Hide resolved
@@ -68,8 +68,10 @@ def connect(self, port=None) -> Optional[str]:
self.disconnect(port)
self._connect_to_port(port)
if temp_locks.get(port):
print("in here")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the print statements in line 71 & 74

Everything else looks good to me!!

Copy link

@nusrat813 nusrat813 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with V1 and V2 protocol

@Laura-Danielle Laura-Danielle merged commit 17a27c7 into edge Nov 27, 2019
@Laura-Danielle Laura-Danielle deleted the lock_tempmodule_poller branch November 27, 2019 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Affects the `api` project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants