ডেডলকগুলি ডিবাগ করার সময় আপনি কী দেখেন?


25

সম্প্রতি আমি এমন প্রকল্পগুলিতে কাজ করছি যা ভারী থ্রেডিং ব্যবহার করে। আমি মনে করি যে আমি তাদের নকশা করার ক্ষেত্রে ঠিক আছি; যতটা সম্ভব স্টেটলেস ডিজাইন ব্যবহার করুন, একাধিক থ্রেডের প্রয়োজন মতো সমস্ত সংস্থানগুলিতে লক অ্যাক্সেস ইত্যাদি function ফাংশনাল প্রোগ্রামিংয়ের আমার অভিজ্ঞতা সেইটিকে ব্যাপক সহায়তা করেছে।

তবে অন্য লোকের থ্রেড কোড পড়ার সময় আমি বিভ্রান্ত হয়ে পড়ি। আমি এখনই একটি অচলাবস্থা ডিবাগ করছি, এবং কোডিং শৈলী এবং নকশা যেহেতু আমার ব্যক্তিগত শৈলীর চেয়ে পৃথক, তাই সম্ভাব্য অচলাবস্থার অবস্থা দেখে আমার বেশ অসুবিধা হচ্ছে।

ডেডলকগুলি ডিবাগ করার সময় আপনি কী দেখেন?


আমি এখানে এসও এর পরিবর্তে এটি জিজ্ঞাসা করছি কারণ আমি আমার সমস্যার কোনও নির্দিষ্ট উত্তর নয়, ডেডলকগুলি ডিবাগ করার বিষয়ে আরও সাধারণ পয়েন্টার চাই।
মাইকেল কে

আমি যে কৌশলগুলি ভাবতে পারি সেগুলি লগ করা (যেমন আরও অনেকে উল্লেখ করেছেন), আসলে-কারা-যার-জন্য-লক-দ্বারা-অপেক্ষার অপেক্ষা করছেন তার অচলাবস্থা গ্রাফ পরীক্ষা করে দেখুন (কারও কারও জন্য স্ট্যাকওভারফ্লো.com/ জিজ্ঞাসা / 3483094/… দেখুন পয়েন্টার) এবং লক টীকাগুলি ( clang.llvm.org/docs/ThreadSafetyAnalysis.html দেখুন )। এটি যদি আপনার কোড নাও হয় তবে আপনি লেখককে টীকা যুক্ত করতে রাজি করার চেষ্টা করতে পারেন - তারা সম্ভবত বাগগুলি খুঁজে পাবেন এবং প্রক্রিয়াটিতে এগুলি (সম্ভবত আপনার সহ) সংশোধন করবেন।
ডন হ্যাচ

উত্তর:


23

যদি পরিস্থিতিটি সত্যিকারের অচলাবস্থার হয় (যেমন দুটি থ্রেড দুটি আলাদা লক ধরেছে তবে কমপক্ষে একটি থ্রেড অন্য থ্রেডকে একটি লক চায়) তারপরে আপনাকে প্রথমে থ্রেডগুলি কীভাবে লকিংয়ের আদেশ দেয় তার সমস্ত প্রাক-ধারণাটি ত্যাগ করতে হবে। কিছুই ধরে নিও না। আপনি যে কোডটি দেখছেন সেখান থেকে আপনি সমস্ত মন্তব্য মুছে ফেলতে চাইতে পারেন, কারণ এই মন্তব্যগুলি আপনাকে এমন কিছু বিশ্বাস করতে পারে যা সত্য বলে মনে করে না। এটি যথেষ্ট জোর দেওয়া কঠিন: কিছুই অনুমান।

এর পরে, কোনও থ্রেড অন্য কোনও লক করার চেষ্টা করার সময় কোন তালা আটকে থাকে তা নির্ধারণ করুন। যদি আপনি পারেন তবে নিশ্চিত করুন যে কোনও থ্রেড লক করা থেকে বিপরীত ক্রমে আনলক হয়েছে। আরও ভাল, একটি থ্রেড একবারে কেবল একটি লক ধরে আছে তা নিশ্চিত করুন।

শ্রমসাধ্যভাবে কোনও থ্রেডের সম্পাদনের মাধ্যমে কাজ করুন এবং সমস্ত লকিং ইভেন্টগুলি পরীক্ষা করুন। প্রতিটি লক-এ, কোনও থ্রেডটি অন্য লকগুলি ধারণ করে কিনা তা নির্ধারণ করুন এবং যদি তাই হয় তবে কোন পরিস্থিতিতে অন্য থ্রেড, অনুরূপ সম্পাদনের পথে করণীয় বিবেচনাধীন লকিং ইভেন্টে যেতে পারে।

সময় এবং অর্থের অভাবের আগে আপনি অবশ্যই সমস্যাটি খুঁজে পাবেন না এটি অবশ্যই সম্ভব।


4
+1 বাহ, এটা হতাশাবাদী ... যদিও এটি সত্য নয়। এটি এমন একটি যা আপনি সমস্ত বাগ খুঁজে পাবেন না। পরামর্শের জন্য ধন্যবাদ!
মাইকেল কে

ব্রুস, আপনার "সত্যিকারের অচলাবস্থার" অনুচ্ছেদটি আমার জন্য অবাক করে। আমি ভেবেছিলাম যে দুটি থ্রেডের মধ্যে অচলাবস্থার সময় যখন প্রতিটি অপরটির কাছে থাকা একটি লকের জন্য অপেক্ষা করে। আপনার সংজ্ঞায় এমন একটি কেস অন্তর্ভুক্ত বলে মনে হয় যে একটি থ্রেড, একটি লক ধরে রাখার সময়, একটি অন্য লকটি অর্জন করার জন্য অপেক্ষা করে যা বর্তমানে একটি অন্য থ্রেড দ্বারা ধারণ করা হয়। এটি আমার কাছে অচলাবস্থার মতো শোনাচ্ছে না; তাই কি??
ডন হ্যাচ

@ ডনহ্যাচ - আমি এটিকে খারাপভাবে বলেছি। আপনি যে পরিস্থিতি বর্ণনা করেছেন তা অচল নয়। আমি এমন একটি পরিস্থিতি ডিবাগিংয়ের গণ্ডগোল জানাতে আশা করেছিলাম যাতে থ্রেড হোল্ডিং লক এ অন্তর্ভুক্ত থাকে, তারপরে লক বি অর্জনের চেষ্টা করা হবে, যখন থ্রেডটি ল ল বি ধারণ করে তা লক এ অর্জন করার চেষ্টা করছে হতে পারে। অথবা হতে পারে পরিস্থিতি আরও অনেক জটিল। লক অধিগ্রহণের ক্রম সম্পর্কে আপনার খুব খোলামেলা ধারণা রাখা দরকার। সমস্ত অনুমান পরীক্ষা। কিছুই বিশ্বাস নেই।
ব্রুস এডিগার

+1 কোডটি সাবধানে পড়ার এবং বিচ্ছিন্নভাবে সমস্ত লক অপারেশন পরীক্ষা করার পরামর্শ দিচ্ছে। কোনও একক নোডের চেয়ে একবারে পুরো বিষয়টিকে একবারে দেখে দেখার চেয়ে যত্ন সহকারে পরীক্ষা করে জটিল গ্রাফটি দেখার পক্ষে আরও সহজ। কেবল কোডটি দেখিয়ে এবং আমার মাথায় বিভিন্ন পরিস্থিতিতে চালিয়ে আমি কতবার সমস্যাটি পেয়েছি।
নিউটোপিয়ান

11
  1. যেমনটি অন্যরা বলেছেন ... আপনি যদি লগিংয়ের জন্য দরকারী তথ্য পেতে পারেন তবে প্রথমে চেষ্টা করুন কারণ এটি করা সবচেয়ে সহজ কাজ।

  2. জড়িত লকগুলি সনাক্ত করুন। সময়কালের জন্য অপেক্ষা করা চিরকালের জন্য অপেক্ষা করা সমস্ত মিউেক্স / সেমোফোরগুলি পরিবর্তন করুন ... হাস্যকরভাবে দীর্ঘ 5 মিনিটের মতো কিছু। সময়টি শেষ হয়ে গেলে ত্রুটিটি লগ করুন। এটি আপনাকে অন্তত ইস্যুতে জড়িত লকগুলির দিক নির্দেশ করবে point সময়ের পরিবর্তনের উপর নির্ভর করে আপনি ভাগ্যবান হয়ে উঠতে পারেন এবং কয়েকটি রান করার পরে উভয় লক খুঁজে পেতে পারেন। সিউডো স্ট্যাক ট্রেস লগ করতে ফাংশন ব্যর্থতার কোড / শর্তাদি ব্যবহার করুন সময়সীমা অপেক্ষা ব্যর্থ হওয়ার পরে আপনি সেখানে কীভাবে প্রথম স্থান পেয়েছিলেন তা সনাক্ত করতে ব্যর্থ হয়। এটি আপনাকে সমস্যার সাথে জড়িত থ্রেড সনাক্ত করতে সহায়তা করবে।

  3. আর একটি জিনিস যা আপনি চেষ্টা করতে পারেন তা হ'ল আপনার মুটেক্স / সেম্যাফোর পরিষেবাগুলির চারপাশে একটি মোড়ক লাইব্রেরি তৈরি করা। প্রতিটি মুটিেক্স কী থ্রেডগুলি রয়েছে এবং কী থ্রেডগুলি মিউটেক্সের জন্য অপেক্ষা করছে তা ট্র্যাক করুন। একটি মনিটরের থ্রেড তৈরি করুন যা কতক্ষণ থ্রেডগুলি ব্লক করে চলেছে তা পরীক্ষা করে। কিছু যুক্তিসঙ্গত সময়কালে ট্রিগার করুন এবং আপনি যে স্ট্যাকটি ট্র্যাক করছেন তার তথ্যটি ফেলে দিন।

এক পর্যায়ে, সরল পুরাতন কোড পরিদর্শন প্রয়োজনীয় হতে চলেছে।


6

প্রথম পদক্ষেপ (যেমন প্যাটার বলেছেন) লগইন হচ্ছে। যদিও আমার অভিজ্ঞতায় এটি প্রায়শই সমস্যাযুক্ত। ভারী সমান্তরাল প্রক্রিয়াকরণে এটি প্রায়শই সম্ভব হয় না। আমাকে একবার নিউরাল নেটওয়ার্কের সাথে অনুরূপ কিছু ডিবাগ করতে হয়েছিল, যা প্রতি সেকেন্ডে 100k নোড প্রসেস করে। ত্রুটিটি কেবল কয়েক ঘন্টা পরে ঘটেছিল এবং এমনকি একটি একক আউটপুট আউটপুটকে এতটাই ধীর করে দেয় যে এটি কয়েক দিন সময় নিতে পারে। যদি লগিং সম্ভব হয় তবে ডেটাতে কম মনোনিবেশ করুন, তবে প্রোগ্রামের প্রবাহে আরও বেশি কিছু করা উচিত, যতক্ষণ না আপনি জানেন যে কোন অংশে এটি ঘটে। প্রতিটি ফাংশনের শুরুতে একটি সাধারণ লাইন এবং আপনি যদি সঠিক ফাংশনটি খুঁজে পেতে পারেন তবে এটি ছোট অংশে বিভক্ত করুন।

অন্য বিকল্পটি বাগের স্থানীয়করণের জন্য কোড এবং ডেটার অংশগুলি সরিয়ে দিচ্ছে। হতে পারে এমন কিছু ছোট প্রোগ্রাম লিখুন যা কেবলমাত্র কিছু ক্লাস নেয় এবং কেবলমাত্র সর্বাধিক প্রাথমিক পরীক্ষা চালায় (এখনও বেশ কয়েকটি থ্রেডে রয়েছে)। জিআই সম্পর্কিত সমস্ত কিছু মুছে ফেলুন, উদাহরণস্বরূপ প্রকৃত প্রসেসিং স্টেট সম্পর্কে কোনও আউটপুট। (আমি ইউজার ইন্টারফেসটি বেশিরভাগ সময় বাগের উত্স হিসাবে খুঁজে পেয়েছি)

আপনার কোডে লকটি শুরু করার এবং এটি ছেড়ে দেওয়ার মধ্যে নিয়ন্ত্রণের সম্পূর্ণ যৌক্তিক প্রবাহ অনুসরণ করার চেষ্টা করুন। একটি সাধারণ ত্রুটি কোনও ফাংশনের শুরুতে লক করা, শেষে আনলক করা হতে পারে তবে এর মাঝে কোথাও শর্তসাপেক্ষ রিটার্ন স্টেটমেন্ট রয়েছে। ব্যতিক্রমগুলিও মুক্তি ছেড়ে দিতে পারে।


"ব্যতিক্রমগুলি মুক্তি দিতে বাধা দিতে পারে" -> আমি যে ভাষাগুলিতে স্কোপড ভেরিয়েবলগুলি নেই সেগুলি নিয়ে আমি মমতা করি: /
ম্যাথিউ এম।

1
@ ম্যাথিয়েউ: স্কোপড ভেরিয়েবল থাকা এবং আসলে এগুলি সঠিকভাবে ব্যবহার করা দুটি ভিন্ন জিনিস হতে পারে। এবং তিনি কোনও নির্দিষ্ট ভাষার উল্লেখ না করেই সাধারণ সমস্যাগুলির জন্য বলেছিলেন। সুতরাং এটি একটি জিনিস, এটি নিয়ন্ত্রণের প্রবাহকে প্রভাবিত করতে পারে।
Thornten müller

3

আমার সেরা বন্ধুরা কোডের মধ্যে আকর্ষণীয় জায়গায় মুদ্রণ / লগ স্টেটমেন্ট হয়েছে। এগুলি সাধারণত অ্যাপ্লিকেশনের অভ্যন্তরে কী ঘটছে তা বিভিন্ন থ্রেডের মধ্যে সময় ব্যাহত না করে আরও ভালভাবে বুঝতে সহায়তা করে যা বাগের পুনরুত্পাদন রোধ করতে পারে।

যদি এটি ব্যর্থ হয়, তবে আমার একমাত্র অবশিষ্ট পদ্ধতিটি কোডটি দেখছে এবং বিভিন্ন থ্রেড এবং ইন্টারঅ্যাকশনগুলির একটি মানসিক মডেল তৈরি করার চেষ্টা করছে এবং দৃশ্যত যা ঘটেছে তা অর্জনের সম্ভাব্য পাগল উপায়গুলি চিন্তা করার চেষ্টা করছে :-) তবে আমি করি না নিজেকে খুব অভিজ্ঞ ডেডলক-স্লেয়ার হিসাবে বিবেচনা করুন। আশা করি অন্যরা আরও ভাল ধারণা দিতে সক্ষম হবেন, যা থেকে আমি খুব শিখতে পারি :-)


1
আমি আজকে এই মত দু'টি মৃত তালকে ডিবাগ করেছি। কৌতুকটি ছিল লথটি অর্জনের আগে এবং পরে ফাংশন, লাইন নম্বর, ফাইলের নাম এবং মিউটেক্স ভেরিয়েবলের নাম (এটি টোকনাইজ করে) মুদ্রণ করে ম্যাক্রো দিয়ে pthread_mutex_lock () মোড়ানো ছিল। Pthread_mutex_unlock () এর জন্যও একই করুন। যখন আমি দেখলাম যে আমার থ্রেডটি হিমশীতল হয়েছে, আমাকে কেবল শেষ দুটি বার্তাগুলির দিকে নজর দিতে হয়েছিল, দুটি থ্রেড লক করার চেষ্টা করছিল কিন্তু কখনই শেষ হয়নি! এখন যা বাকি রয়েছে তা রানটাইমে এটি টগল করার জন্য একটি প্রক্রিয়া যুক্ত করা। :-)
প্লুম্যানেটর

3

প্রথমত, সেই কোডটির লেখক পাওয়ার চেষ্টা করুন। তিনি যা লিখেছেন তা সম্ভবত তার ধারণা থাকবে। এমনকি যদি আপনি দুজন কেবল কথা বলার মাধ্যমে সমস্যাটি চিহ্নিত করতে না পারেন তবে অন্তত আপনি তার সাথে বসে অচলাবস্থার অংশটি চিহ্নিত করতে পারেন, যা আপনাকে সাহায্য ছাড়াই তার কোড বোঝার চেয়ে আরও দ্রুত হবে।

এতে ব্যর্থ হয়ে পেতর টারিকের মতো বলেছিলেন, লগিং সম্ভবত উপায় probably আমি যতদূর জানি, ডিবাগার বহু-থ্রেডিং পরিবেশে খারাপ কাজ করেছেন। লকটি কোথায় রয়েছে তা সনাক্ত করার চেষ্টা করুন, কী কী সংস্থানগুলি অপেক্ষা করছে এবং কী অবস্থায় রেসিংয়ের পরিস্থিতি দেখা দেয় তা সম্পূর্ণ পান।


না, লগিং এখানে আপনার শত্রু - আপনি ধীরে ধীরে লগিং রাখলে আপনি প্রোগ্রামটির আচরণটি এমন পর্যায়ে পরিবর্তন করেন যেখানে লগিং সক্ষম থাকা সাথে পুরোপুরি সূক্ষ্মভাবে চালিত কোনও প্রোগ্রাম পাওয়া সহজ তবে লগিং বন্ধ হয়ে গেলে ডেডলকস। মাল্টিকোর সিপিইউয়ের পরিবর্তে কোনও একক প্রোগ্রাম চালানোর সময় আপনার একই ধরণের সমস্যা হবে।
gbjbaanb

@ জিবিজাবানব, আমি মনে করি এটি বলা আপনার শত্রু অনেক কঠোর। সম্ভবত এটি আপনার সেরা বন্ধু বলা সঠিক হবে, যিনি আপনাকে একবারে হতাশ করেছিলেন। আমি এই পৃষ্ঠায় থাকা আরও বেশ কয়েকজন ব্যক্তির সাথে একমত হব যারা এই কোডের পরীক্ষা ব্যর্থ হওয়ার পরে লগিং করা ভাল প্রথম পদক্ষেপ বলে মনে করেন - প্রায়শই (বাস্তবে বেশিরভাগ সময় আমার অভিজ্ঞতায়) একটি সহজ লগিং কৌশল চিহ্নিত করা হবে সমস্যাটি সহজেই, এবং আপনি শেষ করেছেন। অন্যথায় সব উপায়ে অন্য পদ্ধতি অবলম্বন করুন, তবে আমি সবসময় সহায়ক না হওয়ায় কাজের জন্য সবচেয়ে ভাল সরঞ্জামটি চেষ্টা করা এড়ানো ভাল পরামর্শ বলে আমি মনে করি না।
ডন হ্যাচ

0

এই প্রশ্নটি আমাকে আকর্ষণ করে;) প্রথমত, নিজেকে ভাগ্যবান বিবেচনা করুন যেহেতু আপনি প্রতিটি দৌড়েই ধারাবাহিকভাবে এই সমস্যাটি পুনঃ উত্পাদন করতে পেরেছিলেন। আপনি যদি প্রতিবার একই স্ট্যাকট্রেস দিয়ে একই ব্যতিক্রম পেয়ে থাকেন তবে তা মোটামুটি সোজা-এগিয়ে হওয়া উচিত। যদি তা না হয় তবে স্ট্যাকট্রাককে এত বেশি বিশ্বাস করবেন না, পরিবর্তে কেবল কার্যকর করার সময় বিশ্বব্যাপী অবজেক্টগুলিতে অ্যাক্সেস এবং তার রাজ্যের পরিবর্তনগুলি পর্যবেক্ষণ করুন।


0

আপনার যদি ডেডলকগুলি ডিবাগ করতে হয় তবে আপনি ইতিমধ্যে সমস্যার মধ্যে রয়েছেন। একটি নিয়ম হিসাবে, সংক্ষিপ্ততম সময়ের জন্য লকগুলি ব্যবহার করুন - বা সম্ভব হলে মোটেও নয়। যে কোনও পরিস্থিতি যেখানে আপনি একটি লক নেন এবং তারপরে অপ্রয়োজনীয় কোডে চলে যান এড়ানো উচিত।

এটি অবশ্যই আপনার প্রোগ্রামিংয়ের পরিবেশের উপর নির্ভর করে, তবে আপনার ক্রমিক ক্রমের মতো জিনিসগুলির দিকে নজর দেওয়া উচিত যা আপনাকে কেবল একটি একক থ্রেড থেকে কোনও সংস্থান অ্যাক্সেস করার অনুমতি দিতে পারে।

এবং তারপরে একটি পুরানো তবে অবর্ণনীয় কৌশল রয়েছে: প্রতিটি স্তরকে "স্তর" নির্ধারণ করুন, স্তর 0 থেকে শুরু করে যদি আপনি একটি স্তর 0 লক নেন তবে আপনাকে অন্য কোনও লক অনুমতি দেওয়া হবে না। স্তর 1 লক নেওয়ার পরে আপনি স্তর 0 লক নিতে পারেন। একটি স্তর 10 লক নেওয়ার পরে আপনি 9 বা নিম্ন স্তরগুলিতে লক নিতে পারেন etc.

যদি আপনি এটি করা অসম্ভব বলে মনে করেন তবে আপনাকে নিজের কোডটি ঠিক করতে হবে কারণ আপনি অচল অবস্থায় চলে যাবেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.