मैं सी में एक पर्थ्रेड थ्रेड नाम बदलने के लिए prctl() का उपयोग कर रहा हूं:

  // Set our thread name to assist with debugging a running process
  char *threadName = calloc(16, sizeof(char));
  sprintf(threadName, "My Own Thread");
  prctl(PR_SET_NAME, threadName);

मेरा प्रश्न यह है कि क्या मुझे char *threadName को prctl() कॉल के तुरंत बाद मुक्त कर देना चाहिए या नहीं?

क्या prcrl() स्ट्रिंग परम की एक सुरक्षित प्रतिलिपि लेता है, जिससे मैं जब चाहूं प्रदान किए गए चर को मुक्त कर सकता हूं?

जब मैं मुफ्त में करता हूं तो वालग्रिंड के साथ मेमोरी परीक्षण में कोई समस्या नहीं होती है। मेरी चिंता हार्ड-टू-ट्रेस समरूपता/स्मृति समस्याओं का कारण बन रही है।

संपादित करें: मुझे सुझाए गए प्रश्न पर विश्वास नहीं है क्या कॉलोक को कभी भी मुफ्त में सुरक्षित रूप से उपयोग किया जा सकता है? यहां सिस्टम/कर्नेल फ़ंक्शन और विशेष रूप से prctl() को कॉलर को प्रदान की गई मेमोरी को मुक्त नहीं करने की आवश्यकता होती है।

1
Neal 1 जुलाई 2019, 17:53

2 जवाब

सबसे बढ़िया उत्तर

मुझे स्पष्ट रूप से यह बताते हुए कोई दस्तावेज नहीं मिल रहा है कि prctl( PR_SET_NAME, name ) को पारित स्ट्रिंग को मुक्त करना सुरक्षित है (यह कहीं भी मौजूद हो सकता है)।

मैन पेज, ग्लिबक स्रोत और लिनक्स कर्नेल स्रोत की जांच से संकेत मिलता है कि prctl() को कॉल करने के बाद मेमोरी को मुक्त करना सुरक्षित है।

लिनक्स prctl() मैन पेज इसके लिए यह बताता है PR_SET_NAME:

PR_SET_NAME (Linux 2.6.9 से)

में मान का उपयोग करके कॉलिंग थ्रेड का नाम सेट करें (char *) arg2 द्वारा इंगित किया गया स्थान। नाम तक हो सकता है 16 बाइट लंबा, जिसमें टर्मिनेटिंग नल बाइट भी शामिल है। (यदि स्ट्रिंग की लंबाई, जिसमें टर्मिनेटिंग नल बाइट शामिल है, 16 बाइट्स से अधिक, स्ट्रिंग चुपचाप काट दी जाती है।) यह है वही विशेषता जिसे pthread_setname_np(3) के माध्यम से सेट किया जा सकता है और pthread_getname_np(3) का उपयोग करके पुनर्प्राप्त किया गया। विशेषता है /proc/self/task/[tid]/comm के माध्यम से भी पहुंचा जा सकता है, जहां tid कॉलिंग थ्रेड का नाम है।

यहाँ कुंजी कथन है "इस विशेषता को /proc/self/task/[tid]/comm के माध्यम से भी एक्सेस किया जा सकता है"। इसका मतलब है कि आपूर्ति की गई स्ट्रिंग को कर्नेल स्पेस में कॉपी करना होगा। शब्द "( char * ) arg2 द्वारा इंगित स्थान में मूल्य का उपयोग करना" निश्चित रूप से भ्रमित और अस्पष्ट प्रतीत होता है, इस संभावना के लिए खुला छोड़कर कि prctl() को पास की गई स्ट्रिंग सीधे उपयोग की जाती है। लेकिन "/proc/... के माध्यम से सुलभ होने के लिए कर्नेल स्थान में एक प्रतिलिपि बनाने की आवश्यकता है।

glibc स्रोत का अनुसरण करना थोड़ा कठिन है। जब आपकी प्रक्रिया prctl() को कॉल करती है, तो मैं निश्चित रूप से उस वास्तविक कोड को नहीं ढूंढ सका, जिसे निष्पादित किया गया हो, लेकिन मुझे जो मिला वह सिस्टम कॉल थे जो सीधे कर्नेल को पॉइंटर पास करते थे।

लिनक्स कर्नेल स्रोत बहुत स्पष्ट है। चूंकि स्ट्रिंग को यूजर स्पेस से कर्नेल स्पेस में कॉपी किया जाता है:

case PR_SET_NAME:
    comm[sizeof(me->comm) - 1] = 0;
    if (strncpy_from_user(comm, (char __user *)arg2,
                  sizeof(me->comm) - 1) < 0)
        return -EFAULT;
    set_task_comm(me, comm);
    proc_comm_connector(me);
    break;

नाम सेट करने के लिए prctl() को कॉल करना एक निश्चित परीक्षा होगी, फिर उस स्ट्रिंग को संशोधित करें जिसे prctl() को पास किया गया था। यदि धागे का नाम नहीं बदलता है, तो एक प्रति अवश्य बनाई गई होगी।

2
Andrew Henle 1 जुलाई 2019, 19:15

हां, सामान्य तौर पर, मानक फ़ंक्शन बफ़र्स की प्रतिलिपि बनाएंगे, यदि आवश्यक हो तो लौटने से पहले, कॉलिंग फ़ंक्शन के लिए मूल पास किए गए बफर के स्वामित्व को छोड़ दें।

3
marcolz 1 जुलाई 2019, 18:06