首页 文章 精选 留言 我的

精选列表

搜索[bug],共10000篇文章
优秀的个人博客,低调大师

Teo 0.2.18 发布,修复代码生成 bug,巨好用的网络开发框架

一个后端框架,支持AI编写,不写编程代码就能启动服务器进行增删改查,还能为前端生成请求包,写一个登录功能只需5行代码。支持Node.js,支持Python,支持Rust。使用编程代码的话,它的ORM API可能是世界上最好用,最类型安全的。 使用方法 它的使用方法非常简单,一般我们在编写后端开发的时候,肯定离不开数据建模,编写各个类和表,我们就编写这个,就能得到默认的增删改查和分组聚合。 connector { provider: .sqlite, url: "sqlite::memory:" } server { bind: ("0.0.0.0", 5050) } model User { @id @autoIncrement @readonly id: Int @unique @onSet($if($presents, $isEmail)) email: String name: String? @relation(fields: .id, references: .authorId) posts: Post[] } model Post { @id @autoIncrement @readonly id: Int title: String content: String? @default(false) published: Bool @foreignKey authorId: Int @relation(fields: .authorId, references: .id) author: User } 这就是最精简的博客网站的后台,用户和文章相关联。我们可以对用户和文章进行非常丰富的创建、编辑和查询等操作。 如果要创建一个用户的同时创建其相关联的文章,使用这个请求,发送到/User/create。 { "create": { "email": "ada@teocloud.io", "name": "Ada", "posts": { "create": [ { "title": "Introducing Teo", "content": "This post introduces Teo." }, { "title": "The next generation framework", "content": "Use the next generation technology." } ] } }, "include": { "posts": true } } 这样的返回值会包括用户,也包括文章。 { "data": { "id": 1, "email": "ada@teocloud.io", "name": "Ada", "posts": [ { "id": 1, "title": "Introducing Teo", "content": "This post introduces Teo.", "published": false, "authorId": 1 }, { "id": 2, "title": "The next generation framework", "content": "Use the next generation technology.", "published": false, "authorId": 1 } ] } } 5行代码编写登录 一个集成的登录只需要5行代码。请看演示: @identity.tokenIssuer($identity.jwt(expired: 3600 * 24 * 365)) @identity.jwtSecret(ENV["JWT_SECRET"]!) model User { @id @autoIncrement @readonly id: Int @unique @onSet($if($presents, $isEmail)) @identity.id email: String @writeonly @onSet($presents.bcrypt.salt) @identity.checker($get(.value).presents.bcrypt.verify($self.get(.password).presents)) password: String include handler identity.signIn include handler identity.identity } middlewares [identity.identityFromJwt(secret: ENV["JWT_SECRET"]!)] 这里的代码多于5行,是因为用户表的字段也在这段代码里。把这个请求发送到/User/signIn: { "credentials": { "email": "01@gmail.com", "password": "Aa123456" }} 我们得到了用户信息和他的token。 { "data": { "id": 1, "email": "01@gmail.com" }, "meta": { "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6eyJpZCI6MX0sIm1vZGVsIjpbIlVzZXIiXSwiZXhwIjoxNzQyMTI0NDk2fQ.x2DSIpdnUeJtsUOGQsHlGksr29aF-CWog6X5LILxsOc" }} 完整框架功能一个不少 文件上传,文件返回,静态目录映射,返回HTML页面,或是返回其他内容,一应俱全。Teo的插件是先进的先进后出插件,即第一个插件进入,第二个插件进入,执行路由定义,第二个插件退出,第一个插件退出。 要编写自定义路由,请看这里,这三段代码分别用Node.js,Python和Rust编写,选择你想选择的语言开发后台即可: import { App, Response, RequestCtx } from '@teocloud/teo' import { EchoPathArguments } from './entities' const app = new App() app.mainNamespace().defineHandler("hello", () => { return Response.html(` <html> <head> <title>Hello, Teo handlers</title> </head> <body> <h1>Hello, Teo handlers!</h1> </body> </html> `) }) app.mainNamespace().defineHandler("empty", () => { return Response.empty() }) app.mainNamespace().defineHandler("echo", (ctx: RequestCtx) => { const pathArguments: EchoPathArguments = ctx.pathArguments() return Response.string(pathArguments.data, "text/plain") }) app.run() from asyncio import run from teo import App, Response, RequestCtx from entities import EchoPathArguments async def main(): app = App() def hello_handler(_ctx): return Response.html(""" <html> <head> <title>Hello, Teo handlers</title> </head> <body> <h1>Hello, Teo handlers!</h1> </body> </html> """) app.main_namespace().define_handler("hello", hello_handler) def empty_handler(_ctx): return Response.empty() app.main_namespace().define_handler("empty", empty_handler) def echo_handler(ctx: RequestCtx): path_arguments: EchoPathArguments = ctx.path_arguments() return Response.string(path_arguments["data"], "text/plain") app.main_namespace().define_handler("echo", echo_handler) await app.run() run(main()) mod entities; use tokio::main; use teo::prelude::{App, Response, Result, path}; use crate::entities::EchoPathArguments; #[main] async fn main() -> Result<()> { let app = App::new()?; app.main_namespace_mut().define_handler("hello", || async { let response = Response::html(r#" <html> <head> <title>Hello, Teo handlers</title> </head> <body> <h1>Hello, Teo handlers!</h1> </body> </html> "#)?; Ok::<Response, Error>(response) }); app.main_namespace_mut().define_handler("empty", || async { Ok::<Response, Error>(Response::empty()) }); app.main_namespace_mut().define_handler("echo", |path_args: EchoPathArguments| async move { Ok::<Response, Error>(Response::string(path_args.data(), "text/plain")) }); app.run().await } 在这个例子中,我们定义了三个路由,返回HTML,返回空,和返回文本。 开始使用 Teo的安装过程非常简单,Node.js用npm、pnpm、yarn都可以安装,Python的用pip安装,Rust的用cargo安装,都是语言标配的包管理工具。 npm install @teocloud/teo # node.js pip install teo # python cargo install teo # rust 添加我们的微信群管微信caofz007,关注公众号,在Gitee上面给我们的辛苦劳动一点鼓励,点一颗星,即可加入我们微信群。群里你可以任意问答,我们有专人回复,我们的作者会聆听你的需求,为你改变框架的未来,开发你正需要的功能。 项目地址 官网:https://teocloud.io Gitee: https://gitee.com/teocloud/teo 学习资料 我们的作者花了数月的时间编写文档,我们的官网有详细的文档和教程,现在的浏览器翻译工具非常厉害,只要安装一个翻译插件,网站秒变中文,阅读轻松畅快。

优秀的个人博客,低调大师

PowerToys v0.53.3 发布,修复新功能带来的 bug

Microsoft PowerToys 是 Windows 系统实用程序,供高级用户调整和简化其 Windows 体验,可最大限度地提高生产力。 1月10日,PowerToys 发布了 0.53.1 版本,提供了三个重要的新功能,详情可查看《PowerToys v0.53.1 发布,新增三个重要功能》,1月13日 发布了最新的 0.53.3 版本,修复 0.53.1 版本的三个新功能带来的一些问题: #15364- 修复输入单个字符后 Powertoys 运行滞后的问题,通过在某些计算机上禁用列表虚拟化,以提高滚动速度。 #15305-修复Powertoys运行 Uri 插件出现格式错误的异常问题 #15344- 修复由于社区的插件与 Powertoys 官方插件键同名,而引发的崩溃问题。 更新公告:https://github.com/microsoft/PowerToys/releases/tag/v0.53.3

优秀的个人博客,低调大师

JVM 锁 bug 导致 G1 GC 挂起问题分析和解决

编者按:笔者在 AArch64 中遇到一个 G1 GC 挂起,CPU 利用率高达 300%的案例。经过分析发现问题是由 JVM 的锁机制导致,该问题根因是并发编程中没有正确理解内存序导致。本文着重介绍 JVM 中 Monitor 的基本原理,同时演示了在什么情况下会触发该问题。希望通过本文的分析,读者能够了解到内存序对性能、正确性的影响,在并发编程时更加仔细。 现象 本案例是一个典型的弱内存模型案例,大致的现象就是 AArch64 平台上,业务挂死,而进程占用 CPU 持续维持在 300%。配合 top 和 gdb,可以看到是 3 个 GC 线程在 offer_termination 处陷入了死循环: 多个并行 GC 线程在 Minor GC 结束时调用 offer_termination,在 offer_termination 中自旋等待其他并行 GC 线程到达该位置,才说明 GC 任务完成,可以终止。(关于并行任务的中止协议问题,可以参考相关论文,这里不做着重介绍。 简单地说,在并行任务执行时,多个任务之间可能存在任务不均衡,所以 JVM 内部设计了任务均衡机制,同时必须设计任务终止的机制来保证多个任务都能完成,这里的 offer_termination 就是尝试终止任务)。 在该案例中,部分 GC 线程完成自己的任务,等待其他的 GC 线程。此时出现挂起,很有可能是因为发生了死锁。所以问题很可能是由于那些尚未完成任务的 GC 线程上错误地使用锁。所以使用 gdb 观察了一下其他 GC 线程,发现其他 GC 线程全都阻塞在一把 JVM 的锁上: 而这把 Monitor 中的情况如下: cxq 上积累了大量 GC 线程 OnDeck 记录的 GC 线程已经消失 _owner 记录的锁持有者为 NULL 分析 在进一步分析前,首先普及一下 JVM 锁组件 Monitor 的基本原理,Monitor 类主要包含 4 个核心字段: “Thread * volatile _owner” 字段指向这把锁的持有线程 “SplitWord_LockWord” 字段被设计为 1 个机器字长,目的是为了确保操作时天然的原子性,它的最低位被设计为上锁标记位,而高位区域用来存放 256 字节对齐的竞争队列(cxq)地址 “ParkEvent * volatile_EntryList” 字段指向一个等待队列,跟 cxq 差别不大,个人理解只是为了缓解 cxq 的竞争压力而设计 “ParkEvent * volatile_OnDeck” 字段指向这把锁的法定继承人,同时最低位还充当了内部锁的角色 接下来通过一组流程图来介绍加解锁的具体流程: 上图是加锁的一个整体流程,大致分为 3 步: 首先走快速上锁流程,主要对应锁本身无人持有的最理想情况 接着是自旋上锁流程,这是预期将在短时间内获取锁的情况 最后是慢速上锁流程,申请者将会加入等待队列(cxq),然后进入睡眠,直到被唤醒后发现自己变成了法定继承者,于是进入自旋,直到完成上锁。 而且,基于性能考虑,整个上锁流程中的每一步几乎都做了“插队”的尝试: 如上图代码中所示,“插队”的意思就是不经过排队(cxq),直接尝试置上锁标志位。 上图就是整个解锁流程了,显然真正的解锁操作在第二步中就已经完成了(意味着接下来时刻有“插队”现象发生),剩下的主要就是选出继承者的过程,大致分为以下几步: 解锁线程首先需要将内部锁(_OnDeck)标记上锁 从竞争队列(cxq)抽取所有等待者放入等待队列(_EntryList) _ EntryList 取出头一个元素,写入_OnDeck 的同时解除内部锁标记,这代表选出了继承者 唤醒继承者 当然伴随着整个解锁流程每一步的,还有对“插队”行为的处理。 至此,JVM 锁组件 Monitor 的原理就介绍到这里,再回归到问题本身,一个疑问就是_OnDeck 上记录的继承者为何消失?作为继承者,既然已经消失在竞争队列和等待队列里,显然意味着它大概率已经持有锁、然后解锁走人了,所以问题很可能跟继承者选取过程有关。基于这种猜测,我们对相关代码着重进行了梳理,就发现了下图两处红框标记位置存在疑点,那就是在选继承者过程第 3 步中: 写EntryList 和写_OnDeck 之间没有 barrier 来保证执行顺序,这可能出现_OnDeck 先于EntryList 写入的情况,一旦继承人提前持有锁,后果就可能非常糟糕… 这里贴了一张可能的问题场景: 线程 A 处于解锁流程中,由于乱序,先写入了继承者同时解除内部锁 线程 B 处于上锁流程,发现自己就是法定继承者后,立刻完成上锁 线程 B 又迅速进入解锁流程,并从_EntryList 中取出头元素(也就是线程 B!)作为继承者写入_OnDeck,完成解锁走人 线程 A 此时才更新_EntryList,然后唤醒继承者(也就是线程 B!),完成解锁走人 _OnDeck 上的继承者线程 B,实际已经完成加解锁离开,后续等待线程再也无法被唤醒。 正巧在社区的高版本上找到了一个相关的修复记录,这里贴出 2 个关键的代码片段: 上面这段代码位于慢速上锁流程,被唤醒后检查继承者是否是自己,修复后的代码在读_OnDeck 时加了 Load-Acquire 的 barrier。 上面这段代码位于解锁时选继承者流程,从_ EntryList 取出头一个元素,写入_OnDeck 的同时解除内部锁标记,修复后的代码在写_OnDeck 时加了 Store-Release 的 barrier。 显然,围绕_OnDeck 添加的这对 One-way barrier 可以确保:当继承者线程被唤醒时,该线程可以“看”到_EntryList 已经被及时更新。 总结: 在 AArch64 这种弱内存模型的平台上(关于内存序更多的知识在接下来的分享中会详细介绍),一旦涉及多线程对公共内存的每一次访问,必须反复确认是否需要通过 barrier 来严格保序,而且除非存在有效的依赖关系,否则 barrier 需要在读写端成对使用。 后记 如果遇到相关技术问题(包括不限于毕昇 JDK),可以通过毕昇 JDK 社区求助(目前毕昇 JDK 最新的官网http://bishengjdk.openeuler.org已经上线,可以点击原文进入官网查找所有相关资源,包括二进制下载、代码仓库、使用教学、安装、学习资料等)。 毕昇JDK社区每双周周二举行技术例会,同时有一个技术交流群讨论GCC、LLVM、JDK和V8等相关编译技术,感兴趣的同学可以添加如下微信小助手,回复Compiler入群。 本文分享自微信公众号 - openEuler(openEulercommunity)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

GrammaTech 推出 API bug 检测工具,美国国土安全部赞助

安全测试解决方案公司GrammaTech 推出了一个名为 Swap Detector 的开源工具,可用来检测应用程序编程接口(API)使用错误。 Swap Detector 是美国国土安全部科技局静态工具分析现代化项目(Static Tool Analysis Modernization Project,STAMP)赞助的研究项目的一部分,可改善 DevOps 团队的应用安全测试。该工具可以让开发人员和 DevOps 团队能够识别由于交换函数参数导致的错误(这些错误也可能存在于部署的代码中)。 GrammaTech 研究副总裁 Alexey Loginov 称,“传统的静态分析技术并没有利用开源领域现有的代表无错误编码实践的大量信息。通过Swap Detector,我们将大数据分析技术,也就是我们所说的 Big Code分析,应用到 Fedora RPM 开源库中,以确定正确的 API 使用基准。这让我们开发的错误检测能力远远超过了传统程序分析方法的可扩展性和准确性。” Swap Detector 接口集成了各种静态分析工具,例如 Clang Static Analyzer、Clang-Tidy 和 PyLint。最初,Swap Detector 的研发侧重于C/C++ 程序方面,但如今其已适用于其他语言的程序,特别是对解释型和非编译型的语言来说非常有利。 Swap Detector 采用多种错误检测技术,并将它们层叠在一起以提高准确性。例如,将调用站点中使用的参数名称与相应声明中使用的参数名称进行比较。此外,它还使用了“Big Code”技术,应用从大量代码样本中收集的已知良好 API 使用模式的使用情况的统计信息,并将统计上异常的使用情况标记为潜在的错误。为了提高报告警告的精度,Swap Detector 还对这两种技术的输出采用了减少假阳性的策略。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册