Changeset View
Changeset View
Standalone View
Standalone View
processcore/processes_linux_p.cpp
Show First 20 Lines • Show All 107 Lines • ▼ Show 20 Line(s) | 107 | { | |||
---|---|---|---|---|---|
108 | public: | 108 | public: | ||
109 | Private() { mProcDir = opendir( "/proc" );} | 109 | Private() { mProcDir = opendir( "/proc" );} | ||
110 | ~Private(); | 110 | ~Private(); | ||
111 | inline bool readProcStatus(const QString &dir, Process *process); | 111 | inline bool readProcStatus(const QString &dir, Process *process); | ||
112 | inline bool readProcStat(const QString &dir, Process *process); | 112 | inline bool readProcStat(const QString &dir, Process *process); | ||
113 | inline bool readProcStatm(const QString &dir, Process *process); | 113 | inline bool readProcStatm(const QString &dir, Process *process); | ||
114 | inline bool readProcCmdline(const QString &dir, Process *process); | 114 | inline bool readProcCmdline(const QString &dir, Process *process); | ||
115 | inline bool readProcCGroup(const QString &dir, Process *process); | 115 | inline bool readProcCGroup(const QString &dir, Process *process); | ||
116 | inline long readTgid(long pid); | ||||
117 | inline long readPpid(long pid); | ||||
116 | inline bool getNiceness(long pid, Process *process); | 118 | inline bool getNiceness(long pid, Process *process); | ||
117 | inline bool getIOStatistics(const QString &dir, Process *process); | 119 | inline bool getIOStatistics(const QString &dir, Process *process); | ||
118 | QFile mFile; | 120 | QFile mFile; | ||
119 | char mBuffer[PROCESS_BUFFER_SIZE+1]; //used as a buffer to read data into | 121 | char mBuffer[PROCESS_BUFFER_SIZE+1]; //used as a buffer to read data into | ||
120 | DIR* mProcDir; | 122 | DIR* mProcDir; | ||
123 | bool mShowingThreads; | ||||
121 | }; | 124 | }; | ||
122 | 125 | | |||
123 | ProcessesLocal::Private::~Private() | 126 | ProcessesLocal::Private::~Private() | ||
124 | { | 127 | { | ||
125 | closedir(mProcDir); | 128 | closedir(mProcDir); | ||
126 | } | 129 | } | ||
127 | 130 | | |||
128 | ProcessesLocal::ProcessesLocal() : d(new Private()) | 131 | ProcessesLocal::ProcessesLocal() : d(new Private()) | ||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Line(s) | 214 | if ( mBuffer[0] == '0' && mBuffer[1] == ':' && mBuffer[2] == ':' ) { | |||
212 | process->setCGroup(QString::fromLocal8Bit(&mBuffer[3]).trimmed()); | 215 | process->setCGroup(QString::fromLocal8Bit(&mBuffer[3]).trimmed()); | ||
213 | break; | 216 | break; | ||
214 | } | 217 | } | ||
215 | } | 218 | } | ||
216 | mFile.close(); | 219 | mFile.close(); | ||
217 | return true; | 220 | return true; | ||
218 | } | 221 | } | ||
219 | 222 | | |||
220 | long ProcessesLocal::getParentPid(long pid) { | 223 | long ProcessesLocal::Private::readTgid(long pid) | ||
221 | if (pid <= 0) | 224 | { | ||
222 | return -1; | 225 | long tgid = -1; | ||
223 | d->mFile.setFileName(QStringLiteral("/proc/") + QString::number(pid) + QStringLiteral("/stat")); | 226 | mFile.setFileName(QStringLiteral("/proc/") + QString::number(pid) + QStringLiteral("/status")); | ||
224 | if(!d->mFile.open(QIODevice::ReadOnly)) | 227 | if(!mFile.open(QIODevice::ReadOnly)) | ||
228 | return false; /* process has terminated in the meantime */ | ||||
229 | | ||||
230 | int size; | ||||
231 | while( (size = mFile.readLine( mBuffer, sizeof(mBuffer))) > 0) { //-1 indicates an error | ||||
232 | switch( mBuffer[0]) { | ||||
233 | case 'T': | ||||
234 | if((unsigned int)size > sizeof("Tgid:") && qstrncmp(mBuffer, "Tgid:", sizeof("Tgid:")-1) == 0) | ||||
235 | tgid = atol(mBuffer + sizeof("Tgid:")-1); | ||||
236 | } | ||||
237 | } | ||||
238 | mFile.close(); | ||||
239 | return tgid; | ||||
240 | } | ||||
241 | | ||||
242 | long ProcessesLocal::Private::readPpid(long pid) | ||||
243 | { | ||||
244 | mFile.setFileName(QStringLiteral("/proc/") + QString::number(pid) + QStringLiteral("/stat")); | ||||
245 | if(!mFile.open(QIODevice::ReadOnly)) | ||||
225 | return -1; /* process has terminated in the meantime */ | 246 | return -1; /* process has terminated in the meantime */ | ||
226 | 247 | | |||
227 | int size; //amount of data read in | 248 | int size; //amount of data read in | ||
228 | if( (size = d->mFile.readLine( d->mBuffer, sizeof(d->mBuffer))) <= 0) { //-1 indicates nothing read | 249 | if( (size = mFile.readLine( mBuffer, sizeof(mBuffer))) <= 0) { //-1 indicates nothing read | ||
229 | d->mFile.close(); | 250 | mFile.close(); | ||
230 | return -1; | 251 | return -1; | ||
231 | } | 252 | } | ||
232 | 253 | | |||
233 | d->mFile.close(); | 254 | mFile.close(); | ||
234 | char *word = d->mBuffer; | 255 | char *word = mBuffer; | ||
235 | //The command name is the second parameter, and this ends with a closing bracket. So find the last | 256 | //The command name is the second parameter, and this ends with a closing bracket. So find the last | ||
236 | //closing bracket and start from there | 257 | //closing bracket and start from there | ||
237 | word = strrchr(word, ')'); | 258 | word = strrchr(word, ')'); | ||
238 | if (!word) | 259 | if (!word) | ||
239 | return -1; | 260 | return -1; | ||
240 | word++; //Nove to the space after the last ")" | 261 | word++; //Nove to the space after the last ")" | ||
241 | int current_word = 1; | 262 | int current_word = 1; | ||
242 | 263 | | |||
243 | while(true) { | 264 | while(true) { | ||
244 | if(word[0] == ' ' ) { | 265 | if(word[0] == ' ' ) { | ||
245 | if(++current_word == 3) | 266 | if(++current_word == 3) | ||
246 | break; | 267 | break; | ||
247 | } else if(word[0] == 0) { | 268 | } else if(word[0] == 0) { | ||
248 | return -1; //end of data - serious problem | 269 | return -1; //end of data - serious problem | ||
249 | } | 270 | } | ||
250 | word++; | 271 | word++; | ||
251 | } | 272 | } | ||
252 | long ppid = atol(++word); | 273 | return atol(++word); | ||
253 | if (ppid == 0) | 274 | } | ||
275 | | ||||
276 | long ProcessesLocal::getParentPid(long pid) { | ||||
277 | long ppid; | ||||
278 | if (pid <= 0) | ||||
279 | return -1; | ||||
280 | | ||||
281 | if (d->mShowingThreads) { | ||||
282 | long tgid = d->readTgid(pid); // Thread group ID | ||||
283 | if (tgid == pid) // Thread group leader: show real PPID | ||||
284 | ppid = d->readPpid(pid); | ||||
285 | else | ||||
286 | ppid = tgid; // Non-leader thread: show TGID as PPID | ||||
287 | } else | ||||
288 | ppid = d->readPpid(pid); | ||||
289 | | ||||
290 | if (ppid <= 0) | ||||
254 | return -1; | 291 | return -1; | ||
255 | return ppid; | 292 | return ppid; | ||
256 | } | 293 | } | ||
257 | 294 | | |||
258 | bool ProcessesLocal::Private::readProcStat(const QString &dir, Process *ps) | 295 | bool ProcessesLocal::Private::readProcStat(const QString &dir, Process *ps) | ||
259 | { | 296 | { | ||
260 | QString filename = dir + QStringLiteral("stat"); | 297 | QString filename = dir + QStringLiteral("stat"); | ||
261 | // As an optimization, if the last file read in was stat, then we already have this info in memory | 298 | // As an optimization, if the last file read in was stat, then we already have this info in memory | ||
▲ Show 20 Lines • Show All 281 Lines • ▼ Show 20 Line(s) | 574 | { | |||
543 | if(!d->readProcCmdline(dir, process)) success = false; | 580 | if(!d->readProcCmdline(dir, process)) success = false; | ||
544 | if(!d->readProcCGroup(dir, process)) success = false; | 581 | if(!d->readProcCGroup(dir, process)) success = false; | ||
545 | if(!d->getNiceness(pid, process)) success = false; | 582 | if(!d->getNiceness(pid, process)) success = false; | ||
546 | if(mUpdateFlags.testFlag(Processes::IOStatistics) && !d->getIOStatistics(dir, process)) success = false; | 583 | if(mUpdateFlags.testFlag(Processes::IOStatistics) && !d->getIOStatistics(dir, process)) success = false; | ||
547 | 584 | | |||
548 | return success; | 585 | return success; | ||
549 | } | 586 | } | ||
550 | 587 | | |||
588 | static void getPidsFromDir(DIR *dir, QSet<long> *pids) | ||||
589 | { | ||||
590 | struct dirent* entry; | ||||
591 | while ( ( entry = readdir( dir ) ) ) | ||||
592 | if ( entry->d_name[ 0 ] >= '0' && entry->d_name[ 0 ] <= '9' ) | ||||
593 | pids->insert(atol( entry->d_name )); | ||||
594 | } | ||||
595 | | ||||
551 | QSet<long> ProcessesLocal::getAllPids( ) | 596 | QSet<long> ProcessesLocal::getAllPids( ) | ||
552 | { | 597 | { | ||
553 | QSet<long> pids; | 598 | QSet<long> pids; | ||
554 | if(d->mProcDir==nullptr) return pids; //There's not much we can do without /proc | | |||
555 | struct dirent* entry; | 599 | struct dirent* entry; | ||
600 | if(d->mProcDir==nullptr) return pids; //There's not much we can do without /proc | ||||
556 | rewinddir(d->mProcDir); | 601 | rewinddir(d->mProcDir); | ||
602 | if(d->mShowingThreads) { | ||||
557 | while ( ( entry = readdir( d->mProcDir ) ) ) | 603 | while ( ( entry = readdir( d->mProcDir ) ) ) | ||
558 | if ( entry->d_name[ 0 ] >= '0' && entry->d_name[ 0 ] <= '9' ) | 604 | if ( entry->d_name[ 0 ] >= '0' && entry->d_name[ 0 ] <= '9' ) { | ||
559 | pids.insert(atol( entry->d_name )); | 605 | char *s; | ||
606 | int chars; | ||||
607 | chars = asprintf(&s, "/proc/%s/task/", entry->d_name); | ||||
608 | if (chars == -1) | ||||
609 | return pids; | ||||
610 | DIR *dir = opendir(s); | ||||
611 | if (dir) { | ||||
612 | getPidsFromDir(dir, &pids); | ||||
613 | closedir(dir); | ||||
614 | } | ||||
615 | free(s); | ||||
616 | } | ||||
617 | } else { | ||||
618 | getPidsFromDir(d->mProcDir, &pids); | ||||
619 | } | ||||
560 | return pids; | 620 | return pids; | ||
561 | } | 621 | } | ||
562 | 622 | | |||
563 | bool ProcessesLocal::sendSignal(long pid, int sig) { | 623 | bool ProcessesLocal::sendSignal(long pid, int sig) { | ||
564 | errno = 0; | 624 | errno = 0; | ||
565 | if (pid <= 0) { | 625 | if (pid <= 0) { | ||
566 | errorCode = Processes::InvalidPid; | 626 | errorCode = Processes::InvalidPid; | ||
567 | return false; | 627 | return false; | ||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Line(s) | 786 | case 'M': | |||
728 | d->mFile.close(); | 788 | d->mFile.close(); | ||
729 | return atoll(d->mBuffer + sizeof("MemTotal:")-1); | 789 | return atoll(d->mBuffer + sizeof("MemTotal:")-1); | ||
730 | } | 790 | } | ||
731 | } | 791 | } | ||
732 | } | 792 | } | ||
733 | return 0; // Not found. Probably will never happen | 793 | return 0; // Not found. Probably will never happen | ||
734 | #endif | 794 | #endif | ||
735 | } | 795 | } | ||
796 | | ||||
797 | bool ProcessesLocal::canShowThreads() | ||||
798 | { | ||||
799 | return true; | ||||
800 | } | ||||
801 | | ||||
802 | void ProcessesLocal::setShowingThreads(bool showThreads) | ||||
803 | { | ||||
804 | d->mShowingThreads = showThreads; | ||||
805 | } | ||||
806 | | ||||
736 | ProcessesLocal::~ProcessesLocal() | 807 | ProcessesLocal::~ProcessesLocal() | ||
737 | { | 808 | { | ||
738 | delete d; | 809 | delete d; | ||
739 | } | 810 | } | ||
740 | 811 | | |||
741 | } | 812 | } |