专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Fork之前创建了互斥锁,要警惕死锁问题

  下面的这段代码会导致子进程出现死锁问题,您看出来了吗?includestdio。hincludepthread。hincludeunistd。hincludesyswait。hincludestringusingstd::string;pthreadmutextmutexPTHREADMUTEXINITIALIZER;voidfunc(voidarg){pthreadmutexlock(mutex);for(inti0;i10;i){sleep(1);}pthreadmutexunlock(mutex);returnNULL;}intmain(void){pthreadttid;pthreadcreate(tid,NULL,func,NULL);sleep(5);intretfork();if(ret0){printf(beforegetlock);func(NULL);printf(aftergetlock);return0;}elseif(ret0){pthreadjoin(tid,0);wait(NULL);}else{printf(forkfailed);exit(1);}return0;}
  对上述代码进行编译,并运行:〔rootlocalhosttest3〕gmain。cppg〔rootlocalhosttest3〕。a。outbeforegetlock
  我们发现子进程始终没有打印出aftergetlock的日志。
  对fork熟悉的朋友们应该知道,在fork之后,由于copyonwrite机制,当子进程尝试修改数据时,会导致父子进程的内存分离,这个过程也将父进程中的互斥锁给拷贝了过来,也包括了互斥锁的状态(锁定,释放)。
  在父进程启动时,首先创建了一个线程去执行func函数,为了让该线程在fork之前可以被调度执行,使用了sleep函数让主进程中的主线程让出cpu,从而执行func函数,在func函数中对互斥锁进行了加锁。
  5s后,主进程的主线程sleep结束,从而执行fork函数,产生了子进程,子进程也继承了父进程中的互斥锁,也继承了该锁的锁定状态,因此尝试加锁时,就会出现死锁问题。
  下面通过GDB调试验证我们的分析。使用GDB进行调试
  如果有同志对GDB还不熟悉,请参考https:wizardforcel。gitbooks。io100gdbtipscontentindex。htmlopeninnewwindow〔rootlocalhosttest3〕gdba。out
  首先设置同时调试父子进程(gdb)setdetachonforkoff
  接下来,在fork之前下一个断点,然后进行单步调试。(gdb)b26Breakpoint1at0x401217:filemain。cpp,line26。(gdb)rStartingprogram:homeworkcppprojtest3a。out〔Threaddebuggingusinglibthreaddbenabled〕Usinghostlibthreaddblibrarylib64libthreaddb。so。1。〔NewThread0x7ffff7a8c640(LWP167076)〕Thread1a。outhitBreakpoint1,main()atmain。cpp:2626intretfork();Missingseparatedebuginfos,use:dnfdebuginfoinstallglibc2。3440。el9。x8664libgcc11。3。12。1。el9。x8664libstdc11。3。12。1。el9。x8664(gdb)n〔Newinferior2(process167113)〕Readingsymbolsfromhomeworkcppprojtest3a。out。。。Readingsymbolsfromlib64ldlinuxx8664。so。2。。。〔Threaddebuggingusinglibthreaddbenabled〕Usinghostlibthreaddblibrarylib64libthreaddb。so。1。27if(ret0){Missingseparatedebuginfos,use:dnfdebuginfoinstallglibc2。3440。el9。x8664libgcc11。3。12。1。el9。x8664libstdc11。3。12。1。el9。x8664(gdb)n33elseif(ret0)
  单步到这里,子进程已经创建成功,我们打开另一个窗口查看一下,确实目前父子进程都已经启动了〔rootlocalhost〕psauxgrepvgrepgrepa。outroot1669310。31。418084455780pts0Sl05:290:00gdba。outroot1670720。00。0140202220pts0tl05:290:00homeworkcppprojtest3a。outroot1671130。00。0140201588pts0t05:300:00homeworkcppprojtest3a。out
  这个时候,我们打印一下父进程中mutex的状态,如下所示:(gdb)pmutex1{data{lock1,count0,owner167076,nusers1,kind0,spins0,elision0,list{prev0x0,next0x0}},size0100000000000000244214020001,00repeats26times,align1}
  因为之前父进程中的线程已经执行了func函数,因此锁的lock值为1,即锁定状态,锁的owner时167076,说明该锁由父进程所加。
  接下来,切换到子进程查看:
  单步到执行func函数之前。(gdb)infoinferiorNumDescriptionConnectionExecutable1process1670721(native)homeworkcppprojtest3a。out2process1671131(native)homeworkcppprojtest3a。out(gdb)inferior2〔Switchingtoinferior2〔process167113〕(homeworkcppprojtest3a。out)〕〔Switchingtothread2。1(Thread0x7ffff7a90380(LWP167113))〕00x00007ffff7ba98d7inFork()fromlib64libc。so。6(gdb)nSinglesteppinguntilexitfromfunctionFork,whichhasnolinenumberinformation。0x00007ffff7ba96fainfork()fromlib64libc。so。6(gdb)nSinglesteppinguntilexitfromfunctionfork,whichhasnolinenumberinformation。main()atmain。cpp:2727if(ret0){(gdb)n28printf(beforegetlock);(gdb)nbeforegetlock29func(NULL);
  这个时候,我们查看一下子进程中mutex的状态,可以发现lock的值为1,说明目前该互斥锁已经被加锁。而且可以看到owner也属于父进程。(gdb)pmutex2{data{lock1,count0,owner167076,nusers1,kind0,spins0,elision0,list{prev0x0,next0x0}},size0100000000000000244214020001,00repeats26times,align1}(gdb)
  到此,我们就验证了我们的分析,确实时由于锁的状态的继承,导致了子进程的死锁。如何解决该问题?
  使用pthreadatfork函数在fork子进程之前清理一下锁的状态。includepthread。hintpthreadatfork(void(prepare)(void),void(parent)(void),void(child)(void));
  https:man7。orglinuxmanpagesman3pthreadatfork。3。htmlopeninnewwindow
  pthreadatfork()在fork()之前调用,当调用fork时,内部创建子进程前在父进程中会调用prepare,内部创建子进程成功后,父进程会调用parent,子进程会调用child。
  修改之后,代码如下:includestdio。hincludepthread。hincludeunistd。hincludesyswait。hincludestringusingstd::string;pthreadmutextmutexPTHREADMUTEXINITIALIZER;voidfunc(voidarg){pthreadmutexlock(mutex);for(inti0;i10;i){sleep(1);}pthreadmutexunlock(mutex);returnNULL;}voidclean(){if(pthreadmutextrylock(mutex)!0){pthreadmutexunlock(mutex);}}intmain(void){pthreadttid;pthreadcreate(tid,NULL,func,NULL);sleep(5);pthreadatfork(NULL,NULL,clean);intretfork();if(ret0){printf(beforegetlock);func(NULL);printf(aftergetlock);return0;}elseif(ret0){pthreadjoin(tid,0);wait(NULL);}else{printf(forkfailed);exit(1);}return0;}
  重新编译并运行,死锁问题解决了。〔rootlocalhosttest3〕。a。outbeforegetlockaftergetlock是否还有别的问题?
  同样的代码,只是本此将锁增加了可重入的属性。我们再看看执行结果。includestdio。hincludepthread。hincludeunistd。hincludesyswait。hincludestringusingstd::string;pthreadmutextmutexPTHREADMUTEXINITIALIZER;pthreadmutexattrtmta;voidfunc(voidarg){pthreadmutexlock(mutex);for(inti0;i10;i){sleep(1);}pthreadmutexunlock(mutex);returnNULL;}voidclean(){if(pthreadmutextrylock(mutex)!0){intretpthreadmutexunlock(mutex);printf(retd,ret);}}intmain(void){增加可重入的属性pthreadmutexattrinit(mta);pthreadmutexattrsettype(mta,PTHREADMUTEXRECURSIVE);pthreadmutexinit(mutex,mta);pthreadttid;pthreadcreate(tid,NULL,func,NULL);sleep(5);pthreadatfork(NULL,NULL,clean);intretfork();if(ret0){printf(beforegetlock);func(NULL);printf(aftergetlock);return0;}elseif(ret0){pthreadjoin(tid,0);wait(NULL);}else{printf(forkfailed);exit(1);}return0;}
  执行结果如下:〔rootlocalhosttest3〕。a。outret1beforegetlock
  此时发现再次发生了死锁。
  原因在于可重入锁解锁必须是相同的线程。子进程中的主线程并非加锁线程,因此无法解锁。
  查看glibc中的相关实现:
  https:github。comlatteraglibcblobmasternptlpthreadmutexunlock。copeninnewwindow
  glicpthreadunlock
  可以看到可重入锁解锁时,确实会有owner的检查。并且会返回EPERM的errno,EPERM1,这与我们打印出来的ret1是相一致的。结论fork函数执行后,子进程会继承来自父进程中的锁和锁的状态可重入锁解锁会检查owner,非owner不能解锁。在fork之前如果有创建互斥锁,一定需要小心其状态。

金堂招人啦!岗位多多,千万不要错过好消息!金堂县2022年建圈强链直播带岗招聘会来啦岗位多多找工作的小伙伴下周一(9月26日)下午230直播千万不要错过!成都金堂时代新材料科技有限公司宁德时代新能源科技股份有限公司羊了个羊催生外挂买卖律师当心被诈骗新黄河记者郭梦桐腾讯最近推出的羊了个羊成为当下最火的小游戏,有网友戏谑称第一关是112,第二关是考研,第二关的低通过率也在网络平台催生了一些外挂交易。新黄河记者在某二手买卖平台上发半月谈一滴蜜的科技含量有多少游客在参观蜂箱谢建雯摄对话嘉宾马红艳(宁夏固原市泾源县产业技术研究院副院长)马勇(宁夏天沐蜂业智能养蜂示范基地养蜂人)马园园(宁夏固原市泾源县产业技术研究院检测中心负责人)地处六盘新赛季这样做,让你钻石直冲荣耀!杨玉环明增暗削?元歌加强S29赛季功能优化盘点新增镜头跟随技能优化后,只要拖动技能轮盘,当指示器超出屏幕时,就能获取更多视野信息。基本不需要再拉三指啦只有在玩家向下瞄准视野不足时才产生偏移。镜头回归英雄时S29赛季8款皮肤或将上线,杨玉环传说提上日程,你更期待哪款?哈哈,新赛季来了,新皮肤也会接踵而至,那么在S29新赛季中,到底会上线多少皮肤呢?钟无艳甄姬战令限定,赵云的未来纪元星元,李元芳的赛季新皮,关羽的典藏摩托,戈娅勇者,这就不用说了吧辽宁首阶段赛程轻松,有望以9连胜收官万众瞩目的新赛季CBA联赛将于10月10日正式打响,首阶段依旧采用赛会制,举办地为浙江杭州,对于辽宁男篮来说郭艾伦的回归无疑为球队注入新的动力,但是在外援方面辽宁又遭遇了困难,莫兰争议再现!虽然广东辽宁的悍将都中选一人一城,但粉丝却并不认可头条创作挑战赛CBA新的一人一城悍将现身,可辽宁与广东都有人上榜!CBA联赛新的一人一城人物终于现身,不过这次,辽宁与广东这两支老牌豪强就相继有两人成功上榜。但他们的上榜也是必然的坐落在闽浙赣三省交界的王家大屋探访江西沈万三前世今生故事是最吸引人的,我们总追寻当年凤凰古城翠翠与傩送的纯粹凄美爱情无数人远赴桂林阳朔踏上当年刘三姐以歌定情的足迹,祈求青山为证,绿水为凭般的真挚爱情。广丰作为独立行政区已有1395岁最美绿色森林康养重庆知名作家江津四面山采风宣传活动举行最美绿色森林康养一一重庆知名作家江津四面山采风宣传活动举行重庆市江津区四面山有着神奇北纬28的生物多样性和丹霞地貌,望乡台瀑布水口寺瀑布和珍珠滩瀑布的彩虹,会龙庄古建筑之谜朝源观儒辽宁励志大妈于书前夫出轨,两度瘫痪,一夜白头,55岁终获真爱2021年10月,61岁的辽宁模特于书受到邀请,参加了北京时装周。满头银发,一席华服,61岁的年龄,走出岁月沉淀,走出淡定从容,瞬间掌声响起。谁也无法想象,这是一个两度瘫痪前夫出轨辽宁男篮冠军戒指曝光,第一阶段赛程出炉,签约NBA场均208外援头条创作挑战赛辽宁男篮这个休赛期的操作非常不错,不仅完整保留了上赛季的夺冠阵容,还签下了被称为00后第一中锋的张陈志峰,并将他送往美国进行特训,这样韩德君的接班人问题就彻底解决了。
县级中国人民银行工作人员去向无非三种昨天国务院机构改革方案一经公布,瞬间冲上各大平台热搜榜。公众聚焦在不再保留中国人民银行县(市)支行之后,县级人民银行工作人员何去何从问题上。根据以往国家机构改革经验和各地县市机构合3月9日凌晨,中国又传来25个新消息,认为很有必要告诉大家25专家建议退休人员征收个人所得税,凡是养老金高于五千的,一律征税!对此,你们大家怎么看?网友1提这个馊主意的人非妖即怪,可能吃了唐僧肉,会永远长生不老,永远不领退休金,家里更没有秦刚反击美国后,不到24小时,马克龙联系拜登,联手应对中国挑战秦刚反击美国后,不到24小时,马克龙联系拜登称,联手应对中国挑战就在秦刚外长在记者会上呵斥美国人无下限做法后,美国赶紧跳出来解释称,没有压制中国的意思,并说尊重一个中国原则。然而,代表委员议国是郑春阳委员进一步改革化妆品原料许可机制为推动我国化妆品行业高质量发展,今年全国两会期间,全国政协委员天津强微特生物科技有限公司董事长郑春阳呼吁,进一步改革化妆品原料许可机制,加强化妆品原料负面清单管理,增加注册类新原料亚洲杯8强诞生6席!韩国00爆冷闷平8进4或遭遇中国男足日本或翻车2023年U20亚洲杯决赛阶段C组小组赛最后一轮,韩国男足与塔吉克斯坦男足00战平,约旦男足00战平阿曼男足,最终,韩国队与约旦队分别排在小组第12位晋级8强。至此,本届亚洲杯8强95后文学每次去外公家,外公都会坐在门口的板凳上等我,我总是让他失望,但他却从来不埋怨我。有一年国庆节前,我便盘算着日子,打算给他意外的惊喜。去的那天,帮母亲忙完农活已是傍晚时分。四季分明的观音山上观山水等你,今世途中相见(山水红尘三篇)观音山上观山水红尘是你,人间是你山海是你,彼岸是你玛吉阿米。圆通法中圆法性幡动是我,风动是我心动是我,不动是我仓央嘉措。那一日闭目在经殿香雾中蓦然听见,是你颂经中的真言。那一夜摇动100个有些伤感的小句子精选1。人在变心的时候根本不会刹车2。幸福始终充满着缺陷。3。任何关系走到最后,不过相识一场,心者有所累,无心者无所谓,情出自愿,事过无悔,不负遇见,不谈亏欠。4。以后先了解我再喜欢我世界上最好的养生静心文一藻俗语说心乱则百病生,心静则万病息。越是环境复杂,越要保持心态的平和。处变不惊,得失随缘,人生是一场修心之旅。心静则身安,万物静观皆自得。一个人最好的养生,是静心。保持情绪稳定纠结点赞了很多感同身受的抖音。我却依然还无法释怀。这些年我错了错在优柔寡断错在没主见,一直被別人利用牵着鼻子走。我不知该怎么办无论是在感情还是在孩子身上我都无能为力了。以前那个那么高傲旺自己的10个小妙招1不要纠结,不要内耗,要学会爱自己,包容自己,接纳自己的缺点,只有会爱自己,你才会获得更多的爱。2遇见问题不要逃避,要想着去解决,去正视问题,直面问题。3要用积极的心态去思考人和事
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网