File: procinfo_mac.cpp

package info (click to toggle)
boinc 7.14.2%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,132 kB
  • sloc: cpp: 163,589; php: 113,173; ansic: 49,284; pascal: 35,620; xml: 17,864; java: 13,521; python: 6,551; sh: 4,082; perl: 1,843; makefile: 1,796; objc: 1,543; sql: 959; csh: 126; lisp: 47
file content (160 lines) | stat: -rw-r--r-- 5,487 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2018 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.

#define SHOW_TIMING 0

#include "config.h"
#include <cstdio>

#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>

#if SHOW_TIMING
#include <Carbon/Carbon.h>
#include "client_msgs.h"
#endif

#include "error_numbers.h"
#include "procinfo.h"

#include "mac_branding.h"

using std::vector;

// build table of all processes in system
//
int procinfo_setup(PROC_MAP& pm) {
    int pid = getpid();
    FILE* fd;
    PROCINFO p;
    int c, real_mem, virtual_mem, hours;
    char* lf;
    static long iBrandID = -1;
    
    // For branded installs, the Mac installer put a branding file in our data directory
    FILE *f = fopen("/Library/Application Support/BOINC Data/Branding", "r");
    if (f) {
        fscanf(f, "BrandId=%ld\n", &iBrandID);
        fclose(f);
    }
    if ((iBrandID < 0) || (iBrandID > (NUMBRANDS-1))) {
        iBrandID = 0;
    }

#if SHOW_TIMING
    UnsignedWide start, end, elapsed;

    start = UpTime();
#endif

// Some values of possible interest available from 'ps' command:
// %cpu       percentage cpu usage (alias pcpu)
// %mem       percentage memory usage (alias pmem)
// command    command (executable name)
// majflt     total page faults
// minflt     total page reclaims
// nswap      total swaps in/out
// pagein     pageins (same as majflt)
// pid        process ID
// ppid       parent process ID
// poip       pageouts in progress
// pri        scheduling priority
// rss        resident set size in Kbytes
// time       accumulated cpu time, user + system
// vsz        virtual size in Kbytes
//
// Unfortunately, the selectors majflt, minflt, pagein do not work on OS X, 
// and ps does not return kernel time separately from user time.  
//
// Earlier versions of procinf_mac.C launched a small helper application 
// AppStats using a bi-directional pipe.  AppStats used mach ports to get 
// all the information, including page fault counts, kernel and user times.
// In order to use mach ports, AppStats must run setuid root.
//
// But these three items are not actually used (page fault counts aren't 
// available from Windows either) so we have reverted to using the ps 
// utility, even though it takes more cpu time than AppStats did.
// This eliminates the need to install our own application which runs setuid 
// root; this was perceived by some users as a security risk.

// Under OS 10.8.x (only) ps writes a spurious warning to stderr if called
// from a process that has the DYLD_LIBRARY_PATH environment variable set.
// "env -i command" prevents the command from inheriting the caller's 
// environment, which avoids the spurious warning.
    fd = popen("env -i ps -axcopid,ppid,rss,vsz,pagein,time,command", "r");
    if (!fd) return ERR_FOPEN;

    // Skip over the header line
    do {
        c = fgetc(fd);
        if (c == EOF) {
            pclose(fd);
            return ERR_GETS;
        }
    } while (c != '\n');

    while (1) {
        p.clear();
        c = fscanf(fd, "%d%d%d%d%lu%d:%lf ",
            &p.id,
            &p.parentid,
            &real_mem, 
            &virtual_mem,
            &p.page_fault_count,
            &hours,
            &p.user_time
        );
        if (c < 7) break;
        if (fgets(p.command, sizeof(p.command) , fd) == NULL) break;
        lf = strchr(p.command, '\n');
        if (lf) *lf = '\0';         // Strip trailing linefeed
        p.working_set_size = (double)real_mem * 1024.;
        p.swap_size = (double)virtual_mem * 1024.;
        p.user_time += 60. * (float)hours;
        p.is_boinc_app = (p.id == pid || strcasestr(p.command, "boinc"));
        // Ideally, we should count ScreenSaverEngine.app as a BOINC process
        // only if BOINC is set as the screensaver.  We could set a flag in
        // the client when the get_screensaver_tasks rpc is called, but that
        // would not be 100% reliable for several reasons.
        if (strcasestr(p.command, "screensaverengine")) p.is_boinc_app = true;

        // We do not mark Mac processes as low priority because some processes
        // (e.g., Finder) change priority frequently, which would cause
        // procinfo_non_boinc() and ACTIVE_TASK_SET::get_memory_usage() to get
        // incorrect results for the % CPU used.
        p.is_low_priority = false;

        if (!strcasestr(p.command, brandName[iBrandID])) {
            p.is_boinc_app = true;
        }

        pm.insert(std::pair<int, PROCINFO>(p.id, p));
    }
    
    pclose(fd);

#if SHOW_TIMING
    end = UpTime();
    elapsed = AbsoluteToNanoseconds(SubAbsoluteFromAbsolute(end, start));
    msg_printf(NULL, MSG_INFO, "elapsed time = %llu, m_swap = %lf\n", elapsed, gstate.host_info.m_swap);
#endif
    
    find_children(pm);
    return 0;
}