1 पॉइंट द्वारा GN⁺ 4 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • entr से C प्रोग्राम को बार-बार compile और run करने पर hello असामान्य रूप से बंद हुआ, लेकिन compile output के बाद Segmentation fault संदेश दिखाई नहीं दिया
  • यह संदेश crash हुए प्रोग्राम से नहीं, बल्कि child process को reap करते समय SIGSEGV से termination की पुष्टि करने वाले parent shell द्वारा प्रिंट किया जाता है
  • bash -c को स्पष्ट रूप से लिखने पर भी, अगर वास्तव में चलाने के लिए सिर्फ वही एक कमांड बची हो, तो Bash नया process बनाने के बजाय execve से खुद को replace कर सकता है, जिससे संदेश प्रिंट करने वाला parent shell गायब हो जाता है
  • अलग script में, shebang से शुरू हुआ Bash ./hello को child के रूप में चलाकर उसका इंतज़ार करता है, इसलिए SIGSEGV की पुष्टि कर Segmentation fault (core dumped) प्रिंट करता है
  • ./hello को subshell (./hello) में चलाने या उसके बाद ; true जोड़कर अगला काम बाकी रखने से exec optimization रुकती है और error message की पुष्टि की जा सकती है

संदेश गायब होने वाला execution path

  • नीचे दिए गए entr कमांड से hello.c बदलने पर हर बार compile और run दोहराया जाता है

    ls hello.c | entr -s "gcc -o hello hello.c && ./hello"
    
  • hello segmentation error के कारण बंद हो गया, लेकिन Segmentation fault संदेश या दिखने वाला non-zero exit status के बिना कोई output नहीं बचा

  • कमांड को bash -c में wrap करने पर भी नतीजा वही रहा

    ls hello.c | entr -s "bash -c 'gcc -o hello hello.c && ./hello'"
    
  • वहीं, वही कमांड run.sh में ले जाकर चलाने पर error दिखता है

    #!/bin/bash
    gcc -o hello hello.c && ./hello
    
    ls hello.c | entr -s ./run.sh
    ./run.sh: line 2: 104465 Segmentation fault (core dumped) ./hello
    
  • Segmentation fault प्रिंट कौन करता है

    • crash हुआ प्रोग्राम पहले ही बंद हो चुका होता है, और parent shell child process को reap करते समय यह पुष्टि करने के बाद कि वह SIGSEGV से मरा, संदेश प्रिंट करता है
    • इसलिए यदि संदेश प्रिंट करने के लिए parent shell बचा ही न हो, तो कुछ भी दिखाई नहीं देता
    • bash -c "some_command" में यदि व्यवहारिक रूप से चलाने के लिए बस वही कमांड हो, तो Bash नया process fork किए बिना execve से खुद को replace कर सकता है
    • यह optimization ज़्यादातर executions में बाहर से दिखाई नहीं देती
    • script वाले तरीके में entr ./run.sh को child के रूप में चलाता है, और shebang एक नया Bash शुरू करता है
    • नया Bash gcc चलाने के बाद ./hello को fork करके उसका इंतज़ार करता है, इसलिए child के SIGSEGV termination को देखकर error message छोड़ सकता है

parent shell को बचाए रखने के दो तरीके

  • crash होने वाली कमांड को subshell में चलाने पर संदेश फिर दिखाई देता है
    ls hello.c | entr -s "gcc -o hello hello.c && (./hello)"
    hello.c: line 1: 106595 Segmentation fault (core dumped) ( ./hello )
    
    • parentheses यह मजबूर करते हैं कि ./hello fork किए गए subshell में चले
    • Bash parent की भूमिका बनाए रखता है, इसलिए वह subshell के SIGSEGV termination को reap करके संदेश प्रिंट कर सकता है
  • crash वाली कमांड के बाद करने के लिए कोई काम छोड़ देने से भी exec optimization रुक सकती है
    ls hello.c | entr -s "bash -c 'gcc -o hello hello.c && ./hello; true'"
    bash: line 1: 109516 Segmentation fault (core dumped) ./hello
    
    • ; true की वजह से ./hello खत्म होने के बाद भी Bash के पास काम बचा रहता है, इसलिए वह खुद को उस प्रोग्राम से replace नहीं करता
    • अलग wrapper script के बिना भी segmentation error message की पुष्टि की जा सकती है

1 टिप्पणियां

 
GN⁺ 4 시간 전
Lobste.rs की राय
  • नए Linux distributions में अक्सर default रूप से core dump disable रहता है, जिससे परेशानी होती है
    ulimit -c unlimited से इसे फिर enable किया जा सकता है, लेकिन लगता है core file executable के उसी directory में भी नहीं बनती, और systemd उसे कहीं और ले जाता है
    OpenBSD की तरह core dump default रूप से enable हो और executable के उसी directory में रखा जाए तो अच्छा होगा, लेकिन अभी crash होने पर आम तौर पर executable को gdb के अंदर दोबारा चलाना पड़ता है

    • systemd में coredumpctl से हाल के core dumps की list देखी और उन्हें निकाला जा सकता है
    • core dump को executable वाली जगह पर रखना काफ़ी अजीब विकल्प लगता है
      /usr/bin जैसी जगहों पर core dump ढूंढने का खयाल भी नहीं आएगा, और ऐसी locations अक्सर कम capacity वाले या read-only file system पर होती हैं
      default location के तौर पर working directory कहीं बेहतर नहीं होगी?
    • core files default रूप से disabled होने की वजह शायद यह है कि security experts मानते हैं कि users Linux को सुरक्षित तरीके से operate नहीं कर पाते, और पड़े हुए core files का दुरुपयोग हो सकता है
      यहां तक कि user core files enable भी कर दे, तब भी मानो यह माना जाता है कि उसे पता नहीं कि वह क्या कर रहा है, इसलिए उन्हें ऐसी जगह छिपा दिया जाता है जिसे root के लिए भी ढूंढना मुश्किल हो
  • अगर C या D आदि में program लिखते समय आप जानना चाहते हैं कि वह क्यों terminate हुआ, तो wait system call का return value check करना चाहिए; इससे पता चल सकता है कि program signal की वजह से terminate हुआ या नहीं
    अगर operating system core dump को कहीं और forward करता है, तो ज़रूरत पड़ने पर तुरंत debugging करने या distribution को error report भेजने का फायदा भी मिलता है
    Linux kernel core dump बनाते समय save location तय करने के लिए /proc/sys/kernel/core_pattern नाम की special file पढ़ता है
    file में लिखने के बजाय इसे किसी program को pipe भी किया जा सकता है, जिससे GUI dialog दिखाना, debugger तुरंत launch करना, developer को report email करना जैसे काम संभव हैं
    systemd kernel के core_pattern को अपने managed value पर set करता है, लेकिन systemd का इस्तेमाल न करने पर भी वही kernel feature इस्तेमाल किया जा सकता है
    Windows XP के development के समय core dumps Microsoft को भेजकर ऐसे कई bugs fix किए गए जिनके अस्तित्व का भी शायद पता नहीं था; और Windows पर development tools install करने पर अपने programs develop करते समय on-demand debugger काफी उपयोगी होता है
    यह feature 2003 में Linux में पेश किया गया था, और details man 5 core में देखी जा सकती हैं

  • Core dump debugging के लिए शानदार है, लेकिन अगर उसे असंबंधित-सी files के बगल में रख दिया जाए तो आम users confuse हो सकते हैं, और diagnostic reporting system के रूप में यह भयानक हो सकता है
    submit किए गए Windows crash reports में कितना data जाता है, यह पहली बार देखकर मैं दंग रह गया था
    अगर privacy की रक्षा करने वाले crash reporting system को आधार मानें, तो submitted crashes का diagnosis करने के लिए stack और register information भर से कारण infer करना सीखना होगा

  • यह बात मुझे बिल्कुल नहीं पता थी कि Bash कभी-कभी script के अंदर commands को सीधे exec कर देता है, और यह काफी हैरान करने वाला feature है
    Bash process खुद बहुत भारी भी नहीं होता, और जहां ज़रूरत होती है वहां आदतन exec इस्तेमाल कर लिया जाता है, इसलिए यह कुछ हद तक गलत design किया हुआ feature लगता है
    हालांकि कुल execution counts मिलाकर देखें तो यह उम्मीद से बड़ा फर्क पैदा कर सकता है