Title: Infinite loop when setting value in record's `on_update` callback · Issue #201 · DiamondLightSource/pythonSoftIOC · GitHub
Open Graph Title: Infinite loop when setting value in record's `on_update` callback · Issue #201 · DiamondLightSource/pythonSoftIOC
X Title: Infinite loop when setting value in record's `on_update` callback · Issue #201 · DiamondLightSource/pythonSoftIOC
Description: There is an infinite loop possible when using a record with always_update=True and blocking=True. Run the following IOC: # Import the basic framework components. from softioc import softioc, builder, asyncio_dispatcher # Create an asynci...
Open Graph Description: There is an infinite loop possible when using a record with always_update=True and blocking=True. Run the following IOC: # Import the basic framework components. from softioc import softioc, builde...
X Description: There is an infinite loop possible when using a record with always_update=True and blocking=True. Run the following IOC: # Import the basic framework components. from softioc import softioc, builde...
Opengraph URL: https://github.com/DiamondLightSource/pythonSoftIOC/issues/201
X: @github
Domain: patch-diff.githubusercontent.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Infinite loop when setting value in record's `on_update` callback","articleBody":"There is an infinite loop possible when using a record with `always_update=True` and `blocking=True`. Run the following IOC:\n\n```\n# Import the basic framework components.\nfrom softioc import softioc, builder, asyncio_dispatcher\n\n# Create an asyncio dispatcher, the event loop is now running\ndispatcher = asyncio_dispatcher.AsyncioDispatcher()\n\n# Set the record prefix\nbuilder.SetDeviceName(\"MY-DEVICE-PREFIX\")\n\n# Create some records\nasync def wrapped_method(value):\n print(\"In callback\")\n record.set(0, process=False)\n\nrecord = builder.Action(\n \"TEST\",\n on_update=wrapped_method,\n blocking=True,\n initial_value=0,\n ZNAM=\"Idle\",\n ONAM=\"Active\",\n )\n\n# Boilerplate get the IOC started\nbuilder.LoadDatabase()\nsoftioc.iocInit(dispatcher)\n\n# Finally leave the IOC running with an interactive shell.\nsoftioc.interactive_ioc(globals())\n\n```\nand do `caput MY-DEVICE-PREFIX:TEST 1`. In the IOC output console you will see the `print` statement repeating forever, despite `process=False`.\n\nThe reason for this is that when `blocking=True` is specified, it changes how EPICS executes the `db_put_field` command present in the `record.set` method. It returns immediately, rather than running synchronously. This causes our logic that tracks the `process=False` request to break, and effectively put it back to the default value of `process=True`. \n\nIt is not immediately obvious what the fix is for this; we need to somehow associate the async callback with the initial synchronous `record.set`, but there is no way to pass context into the EPICS processing chain. \n\nThis issue originally found in https://github.com/DiamondLightSource/FastCS/issues/291.","author":{"url":"https://github.com/AlexanderWells-diamond","@type":"Person","name":"AlexanderWells-diamond"},"datePublished":"2026-02-02T10:06:11.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/201/pythonSoftIOC/issues/201"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:5dd10983-067f-d9cf-9c13-7bc3e2c416a9 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | BB1E:11D1F7:2556BB:32BE7B:6982631A |
| html-safe-nonce | 7f98b40c2284d4b7009712b8cec4515c257495939a68984d6fee15b0035bb0b9 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCQjFFOjExRDFGNzoyNTU2QkI6MzJCRTdCOjY5ODI2MzFBIiwidmlzaXRvcl9pZCI6IjcwMjgzMDIxODAyMDk4MTIyNTAiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 20edaacd90d8b46ae7ebae2e1e2defef62529e80514daf7e576d0c04f109d08d |
| hovercard-subject-tag | issue:3885060136 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/DiamondLightSource/pythonSoftIOC/201/issue_layout |
| twitter:image | https://opengraph.githubassets.com/1cca5f3c31232bbf55ef1335d8541fa67033342f35b98d5458852d760dd33d17/DiamondLightSource/pythonSoftIOC/issues/201 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/1cca5f3c31232bbf55ef1335d8541fa67033342f35b98d5458852d760dd33d17/DiamondLightSource/pythonSoftIOC/issues/201 |
| og:image:alt | There is an infinite loop possible when using a record with always_update=True and blocking=True. Run the following IOC: # Import the basic framework components. from softioc import softioc, builde... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | AlexanderWells-diamond |
| hostname | github.com |
| expected-hostname | github.com |
| None | 82a2ec7faf3b85991d40091f37cdc8035653d1a2ca08b1e6f36670ac6c91d893 |
| turbo-cache-control | no-preview |
| go-import | github.com/DiamondLightSource/pythonSoftIOC git https://github.com/DiamondLightSource/pythonSoftIOC.git |
| octolytics-dimension-user_id | 1233618 |
| octolytics-dimension-user_login | DiamondLightSource |
| octolytics-dimension-repository_id | 20049394 |
| octolytics-dimension-repository_nwo | DiamondLightSource/pythonSoftIOC |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 20049394 |
| octolytics-dimension-repository_network_root_nwo | DiamondLightSource/pythonSoftIOC |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | b83d89864fafc7a67b8747b788f52c909d47dbfd |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width