惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cisco Talos Blog
Cisco Talos Blog
P
Privacy & Cybersecurity Law Blog
I
Intezer
Y
Y Combinator Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
Netflix TechBlog - Medium
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Stack Overflow Blog
Stack Overflow Blog
Hacker News: Ask HN
Hacker News: Ask HN
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog
T
Tor Project blog
C
Cybersecurity and Infrastructure Security Agency CISA
云风的 BLOG
云风的 BLOG
博客园_首页
V2EX - 技术
V2EX - 技术
T
Threat Research - Cisco Blogs
腾讯CDC
宝玉的分享
宝玉的分享
博客园 - 叶小钗
罗磊的独立博客
S
Securelist
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
Scott Helme
Scott Helme
博客园 - 司徒正美
W
WeLiveSecurity
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Secure Thoughts
NISL@THU
NISL@THU
N
News and Events Feed by Topic
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
K
Kaspersky official blog
IT之家
IT之家

ddadaal.me

fork subgen实现纯本地AI视频字幕生成和翻译 - ddadaal.me 把nanobot关进Docker后,如何同时保留浏览器可视化与自动化 - ddadaal.me 可划分显存 != 统一内存:AI Max+ 395 64G AI推理性能 2025年总结 - ddadaal.me 14寸16核32线程:搭载AMD AI Max+ 395的HP战99 Ultra使用感受 Node是并发性能的绊脚石吗?测试Express服务器的基准并发能力 - ddadaal.me 用大模型总结文章:效果很好,但是玄学 - ddadaal.me 2024年总结 - ddadaal.me 在西雅图,给生活换个环境 - ddadaal.me 从调库到翻源代码:给wakapi增加SQL Server支持 - ddadaal.me 增加自制博客点击量统计 - ddadaal.me 博客集成AI文章总结功能 - ddadaal.me 2023年总结 - ddadaal.me 博客的发展2:重写,重生 - ddadaal.me 2022年总结 - ddadaal.me 2021年总结 - ddadaal.me 我的第一个真实项目:总结和经验 - ddadaal.me 一次生产环境的文件丢失事故:复盘和教训 - ddadaal.me react-typed-i18n: 使用Template Literal Types实现强类型的i18n - ddadaal.me wslg初体验:最佳Linux发行版? - ddadaal.me 借助Docker,把VPN当作HTTP代理来用 - ddadaal.me 2020年总结 - ddadaal.me 美好的回忆和未知的未来:写在研究生开学前 - ddadaal.me 使用X11 Forwarding在WSL 2中运行GUI程序 - ddadaal.me 在小手机已经消失的时代,我选择了Galaxy S20 - ddadaal.me 使用PowerShell脚本让UWP应用使用localhost上的系统代理 - ddadaal.me 安装Arch Linux并使用N卡玩Steam游戏 - ddadaal.me 可靠性、辅助功能和多屏协同:我对智能手表的体验和看法 - ddadaal.me 从VSCode到Vim到……两个都用? - ddadaal.me 2019年总结 - ddadaal.me 入手4K显示器:LG 27UL550 - ddadaal.me 暗色模式上线 - ddadaal.me 修复gatsby-transformer-remark插件中文词数统计错误问题 - ddadaal.me 折腾Linux: 从实体机到Win10 - ddadaal.me 从viccrubs改名为ddadaal - ddadaal.me A React Form Component Performance Optimization with Profiler 博客的发展一:RSS,国内托管…… - ddadaal.me 2016至2019,和南京大学微软学生俱乐部一起成长 - ddadaal.me 北大信科 | 上交软院 | 南大软院夏令营经历 使用MVC、MVP、MVVM和FRP实现Android局域网群聊应用 - ddadaal.me 2019年春微软实习面试经验 - ddadaal.me Strongly Typed i18n with TypeScript A Kotlin DI Framework in 50 Lines and Thoughts on Kotlin 7天Hackathon,Web前端极速入门指南 - ddadaal.me Simstate and Why - ddadaal.me 2018年总结 - ddadaal.me MSRA DKI组前端面经 - ddadaal.me Safety/Security and Extensibility/Scalability in Software System Design and Architecture 微软听听文档体验报告 - ddadaal.me 正则语法分析器和LALR(1)词法分析器 - ddadaal.me 新博客正式上线 - ddadaal.me 写代码要动脑子! - ddadaal.me 2017年总结 - ddadaal.me Python语言实现的符合本福特定律的十进制固定长度随机数发生器 - ddadaal.me 院自建GitLab CI配置实录 - ddadaal.me C++测例查看器 - ddadaal.me C++插件在VS2017上无法使用的分析 - ddadaal.me
An Infinite Loop Caused by Updating a Map during Iteration
2019-02-25 · via ddadaal.me

✨AI全文摘要

DeepSeek R1DeepSeek R1 8B

The author encountered an infinite loop in a Map iteration during Simstate 2.0 development. The loop occurred when iterating a Map storing React component observers. The root cause was modifying the Map during iteration: calling an observer triggered component re-renders, which unsubscribed (deleted) and resubscribed (re-added) the same function key within the loop. Though the key (function) remained identical, reinsertion during iteration caused the Map to treat it as new, perpetuating the loop. This behavior, dangerous in most languages, arises in JavaScript when altering a Map mid-iteration. The solution involved recognizing indirection-induced complexity and avoiding such mutations during iteration.

Azure AI部署的DeepSeek-R1模型推理

The Problem

I accidently encountered a problem during the development of the 2.0 version of simstate: During an iteration of a set of observers stored in a ES6 Map, which contained only one element, an infinite loop occurred.

Loop that never ends
Loop that never ends

Investigation

This problem confused me quite a lot. It had been confirmed that this Map had only one element and the element remained unchanged between and inside loops, and the all elements in promises array were the same.

Only one element in the map
Only one element in the map

My first thought was data race. It might be true for other languages with real multi-threading capability, but this is JavaScript: it is single thread only, and so there would be no such concurrent related problems.

Using a function as the key of Map seemed weird for other programming languages, since most Map-like data structure (like HashMap in Java, Dictionary in C# and unordered_map in C++) requires the key to be hashable, and functions are not, at least in the surface. However, MDN clearly states that any value (both objects and primitive values) may be used as a key. The following code works well, which proves that functions, too, can be used as keys in a Map.

const data = [];
const map = new Map();
function a() { console.log("a"); }
map.set(a, "123");
map.forEach((value, key) => key()); // a

The Root of the Problem

After some investigation, the call to observer caught my eyes.

observer() will trigger the re-render of observer component and make the updated state available for end-user. To simplify implementation, every time the component is re-rendered, the component will unsubscribe (delete an entry from a Map) to the stores it subscribes to, and re-subscribe (set an entry in a Map) during the render.

StoreConsumer.tsx omitting some unrelated code

export default class StoreConsumer extends React.Component<Props, State> {
  // ...
  instances = new Set<Store<any>>();
 
  // ...
  private unsubscribeAll() {
    this.instances.forEach((store) => {
      // highlight-next-line
      store.unsubscribe(this.update);
    });
  }
 
  useStore = <ST extends StoreType<any>>(storeType: ST, dep?: Dependency<ST>): InstanceType<ST> => {
    // ...
    // highlight-next-line
    store.subscribe(this.update, dep);
    // ...
  }
 
  render() {
    return (
      <SimstateContext.Consumer>
        {(map) => {
          // ...
          // highlight-next-line
          this.unsubscribeAll();
          this.instances.clear();
          return this.props.children({ useStore: this.useStore });
        }}
      </SimstateContext.Consumer>
    );
  }
}

Store.ts omitting unrelated code

subscribe(observer: Observer, dep?: Dependency) {
  // highlight-next-line
  this.observers.set(observer, { dep, shouldUpdate: getChecker(dep) });
}
 
unsubscribe(observer: Observer) {
  // highlight-next-line
  this.observers.delete(observer);
}

The call to observer (observer()), happened during the iteration of the Map, alters the Map itself!

This is a dangerous action. It has become a common sense not to do so in most programming languages, since it might cause unexpected behaviors, which is exactly what happened here.

In this case, when deleting an entry and re-add an entry during the iteration, even if they are the equal, the item will be considered as a new item, which results in an infinite loop.

You may reproduce the case with the following code snippet. Note that since it runs indefinitely, consider running the script in a CLI environment (instead of browser) where you can kill the process to end the execution with ease.

const map = new Map();
function obs() { map.delete(obs); map.set(obs, 1); console.log("obs called"); }
map.set(obs, 1);
map.forEach((value, key) => key());
// endless "obs called"

Conclusion

This is quite a simple problem, and the cause is also easy to understand for most programmers. However, it still confused me for quite a while. After it, I realized that some bugs might seem strange and difficult to debug, but it doesn't mean the cause is complicated: sometimes it is the indirections on top of all the root that adds to the difficulty. During debugging, it is a good way to track down the code execution flow, and in this process the cause may just reveal itself.