~ubuntu-branches/ubuntu/lucid/boinc/lucid

« back to all changes in this revision

Viewing changes to lib/util.C

  • Committer: Bazaar Package Importer
  • Author(s): Frank S. Thomas, Frank S. Thomas
  • Date: 2008-05-31 08:02:47 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080531080247-4ce890lp2rc768cr
Tags: 6.2.7-1
[ Frank S. Thomas ]
* New upstream release.
  - BOINC Manager: Redraw disk usage charts immediately after connecting to
    a (different) client. (closes: 463823)
* debian/copyright:
  - Added the instructions from debian/README.Debian-source about how
    repackaged BOINC tarballs can be reproduced because DevRef now
    recommends to put this here instead of in the afore-mentioned file.
  - Updated for the new release.
* Removed the obsolete debian/README.Debian-source.
* For consistency upstream renamed the core client and the command tool
  ("boinc_client" to "boinc" and "boinc_cmd" to "boinccmd"). Done the same
  in all packages and created symlinks with the old names for the binaries
  and man pages. Also added an entry in debian/boinc-client.NEWS explaining
  this change.
* debian/rules: Do not list Makefile.ins in the clean target individually,
  just remove all that can be found.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
// To view the GNU Lesser General Public License visit
16
16
// http://www.gnu.org/copyleft/lesser.html
17
17
// or write to the Free Software Foundation, Inc.,
18
 
// 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 
20
20
#if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_)
21
21
#include "boinc_win.h"
30
30
 
31
31
#ifndef _WIN32
32
32
#include "config.h"
33
 
#include <string>
34
 
#include <cstring>
35
 
#include <cstdlib>
36
 
#include <cstdio>
37
 
#include <cmath>
38
 
#include <algorithm>
39
 
#include <iterator>
40
 
#include <iostream>
41
 
#include <fstream>
42
 
#include <cctype>
 
33
#if HAVE_UNISTD_H
 
34
#include <unistd.h>
 
35
#endif
43
36
#include <sys/types.h>
44
 
#include <sys/stat.h>
 
37
#include <sys/time.h>
45
38
#include <sys/wait.h>
46
 
#include <fcntl.h>
47
 
#include <grp.h>
 
39
#include <signal.h>
 
40
#include <sys/resource.h>
48
41
#include <errno.h>
49
 
#include <sys/time.h>
50
 
#include <sys/resource.h>
51
 
#include <unistd.h>
52
 
#include <sys/file.h>
 
42
#include <string>
 
43
#include <cstring>
53
44
#endif
54
45
 
55
 
 
56
46
#include "error_numbers.h"
57
47
#include "common_defs.h"
58
48
#include "filesys.h"
59
49
#include "util.h"
 
50
#include "base64.h"
 
51
#include "mfile.h"
 
52
#include "miofile.h"
 
53
#include "parse.h"
 
54
 
60
55
 
61
56
#ifdef _USING_FCGI_
62
57
#include "fcgi_stdio.h"
66
61
using std::string;
67
62
using std::vector;
68
63
 
69
 
int      g_use_sandbox = 0;
70
 
 
71
64
#define EPOCHFILETIME_SEC (11644473600.)
72
65
#define TEN_MILLION 10000000.
73
66
 
105
98
#ifdef _WIN32
106
99
    ::Sleep((int)(1000*seconds));
107
100
#else
108
 
    unsigned int rem = (int) seconds;
 
101
    double end_time = dtime() + seconds - 0.01;
 
102
    // sleep() and usleep() can be interrupted by SIGALRM,
 
103
    // so we may need multiple calls
 
104
    //
109
105
    while (1) {
110
 
        rem = sleep(rem);
111
 
        if (rem == 0) break;
112
 
        if (rem > seconds) break;   // paranoia
 
106
        if (seconds >= 1) {
 
107
            sleep((unsigned int) seconds);
 
108
        } else {
 
109
            usleep((int)fmod(seconds*1000000, 1000000));
 
110
        }
 
111
        seconds = end_time - dtime();
 
112
        if (seconds <= 0) break;
113
113
    }
114
 
    int x = (int)fmod(seconds*1000000, 1000000);
115
 
    if (x) usleep(x);
116
114
#endif
117
115
}
118
116
 
172
170
}
173
171
 
174
172
static void get_elapsed_time(double& cpu) {
175
 
    static bool first = true;
176
 
    static DWORD first_count = 0;
 
173
    static double start_time;
177
174
 
178
 
    if (first) {
179
 
        first_count = GetTickCount();
180
 
        first = false;
 
175
    double now = dtime();
 
176
    if (start_time) {
 
177
        cpu = now - start_time;
 
178
    } else {
 
179
        cpu = 0;
181
180
    }
182
 
    // TODO: Handle timer wraparound
183
 
    DWORD cur = GetTickCount();
184
 
    cpu = ((cur - first_count)/1000.);
 
181
    start_time = now;
185
182
}
186
183
 
187
184
int boinc_calling_thread_cpu_time(double& cpu) {
193
190
 
194
191
#else
195
192
 
196
 
pthread_mutex_t getrusage_mutex = PTHREAD_MUTEX_INITIALIZER;
197
 
 
198
 
// Unix: pthreads doesn't seem to provide an API for getting
199
 
// per-thread CPU time.  So just get the process's CPU time
 
193
// Unix: pthreads doesn't provide an API for getting per-thread CPU time,
 
194
// so just get the process's CPU time
200
195
//
201
196
int boinc_calling_thread_cpu_time(double &cpu_t) {
202
 
    int retval=1;
203
197
    struct rusage ru;
204
198
 
205
 
    // getrusage can return an error, so try a few times if it returns an error.
206
 
    //
207
 
    if (!pthread_mutex_trylock(&getrusage_mutex)) {
208
 
        for (int i=0; i<10; i++) {
209
 
            retval = getrusage(RUSAGE_SELF, &ru);
210
 
            if (!retval) break;
211
 
        }
212
 
        pthread_mutex_unlock(&getrusage_mutex);
213
 
    }
214
 
    if (retval) {
215
 
        return ERR_GETRUSAGE;
216
 
    }
217
 
    // Sum the user and system time
218
 
    //
219
 
    cpu_t = (double)ru.ru_utime.tv_sec + (((double)ru.ru_utime.tv_usec) / ((double)1000000.0));
220
 
    cpu_t += (double)ru.ru_stime.tv_sec + (((double)ru.ru_stime.tv_usec) / ((double)1000000.0));
 
199
    int retval = getrusage(RUSAGE_SELF, &ru);
 
200
    if (retval) return ERR_GETRUSAGE;
 
201
    cpu_t = (double)ru.ru_utime.tv_sec + ((double)ru.ru_utime.tv_usec) / 1e6;
 
202
    cpu_t += (double)ru.ru_stime.tv_sec + ((double)ru.ru_stime.tv_usec) / 1e6;
221
203
    return 0;
222
204
}
223
205
 
286
268
    avg_time = now;
287
269
}
288
270
 
 
271
#ifndef _USING_FCGI_
289
272
#ifndef _WIN32
290
 
int lookup_group(char* name, gid_t& gid) {
291
 
    struct group* gp = getgrnam(name);
292
 
    if (!gp) return ERR_GETGRNAM;
293
 
    gid = gp->gr_gid;
294
 
    return 0;
295
 
}
296
 
#endif
 
273
// (linux) return current CPU time of the given process
 
274
//
 
275
double linux_cpu_time(int pid) {
 
276
    FILE *file;
 
277
    char file_name[24];
 
278
    unsigned long utime = 0, stime = 0;
 
279
    int n;
 
280
 
 
281
    sprintf(file_name,"/proc/%d/stat",pid);
 
282
    if ((file = fopen(file_name,"r")) != NULL) {
 
283
        n = fscanf(file,"%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%lu%lu",&utime,&stime);
 
284
        fclose(file);
 
285
        if (n != 2) return 0;
 
286
    }
 
287
    return (double)(utime + stime)/100;
 
288
}
 
289
#endif
 
290
#endif
 
291
 
 
292
void boinc_crash() {
 
293
#ifdef _WIN32
 
294
        DebugBreak();
 
295
#else
 
296
        *(int*)0 = 0;
 
297
#endif
 
298
}
 
299
 
 
300
// read file (at most max_len chars, if nonzero) into malloc'd buf
 
301
//
 
302
int read_file_malloc(const char* path, char*& buf, int max_len, bool tail) {
 
303
    FILE* f;
 
304
    int retval, isize;
 
305
    double size;
 
306
 
 
307
    retval = file_size(path, size);
 
308
    if (retval) return retval;
 
309
 
 
310
    f = fopen(path, "r");
 
311
    if (!f) return ERR_FOPEN;
 
312
 
 
313
#ifndef _USING_FCGI_
 
314
    if (max_len && size > max_len) {
 
315
        if (tail) {
 
316
            fseek(f, (long)size-max_len, SEEK_SET);
 
317
        }
 
318
        size = max_len;
 
319
    }
 
320
#endif
 
321
    isize = (int) size;
 
322
    buf = (char*)malloc(isize+1);
 
323
    size_t n = fread(buf, 1, isize, f);
 
324
    buf[n] = 0;
 
325
    fclose(f);
 
326
    return 0;
 
327
}
 
328
 
 
329
// read file (at most max_len chars, if nonzero) into string
 
330
//
 
331
int read_file_string(const char* path, string& result, int max_len, bool tail) {
 
332
    result.erase();
 
333
    int retval;
 
334
    char* buf;
 
335
 
 
336
    retval = read_file_malloc(path, buf, max_len, tail);
 
337
    if (retval) return retval;
 
338
    result = buf;
 
339
    free(buf);
 
340
    return 0;
 
341
}
297
342
 
298
343
// chdir into the given directory, and run a program there.
299
344
// If nsecs is nonzero, make sure it's still running after that many seconds.
300
345
//
301
346
// argv is set up Unix-style, i.e. argv[0] is the program name
302
347
//
 
348
 
303
349
#ifdef _WIN32
304
350
int run_program(
305
351
    const char* dir, const char* file, int argc, char *const argv[], double nsecs, HANDLE& id
308
354
    PROCESS_INFORMATION process_info;
309
355
    STARTUPINFO startup_info;
310
356
    char cmdline[1024];
 
357
    char error_msg[1024];
311
358
    unsigned long status;
312
359
 
313
360
    memset(&process_info, 0, sizeof(process_info));
314
361
    memset(&startup_info, 0, sizeof(startup_info));
315
 
             
 
362
    startup_info.cb = sizeof(startup_info);
 
363
 
316
364
    strcpy(cmdline, "");
317
 
    for (int i=1; i<argc; i++) {
 
365
    for (int i=0; i<argc; i++) {
318
366
        strcat(cmdline, argv[i]);
319
 
        strcat(cmdline, " ");
 
367
        if (i<argc-1) {
 
368
            strcat(cmdline, " ");
 
369
        }
320
370
    }
321
371
 
322
372
    retval = CreateProcess(
325
375
        NULL,
326
376
        NULL,
327
377
        FALSE,
328
 
        CREATE_NEW_PROCESS_GROUP,
 
378
        0,
329
379
        NULL,
330
380
        dir,
331
381
        &startup_info,
332
382
        &process_info
333
383
    );
334
 
    if (retval) return retval;
 
384
    if (!retval) {
 
385
        windows_error_string(error_msg, sizeof(error_msg));
 
386
        fprintf(stderr, "CreateProcess failed: '%s'\n", error_msg);
 
387
        return -1; // CreateProcess returns 1 if successful, false if it failed.
 
388
    }
 
389
 
335
390
    if (nsecs) {
336
391
        boinc_sleep(nsecs);
337
392
        if (GetExitCodeProcess(process_info.hProcess, &status)) {
350
405
    int retval;
351
406
    int pid = fork();
352
407
    if (pid == 0) {
353
 
        retval = chdir(dir);
354
 
        if (retval) return retval;
 
408
        if (dir) {
 
409
            retval = chdir(dir);
 
410
            if (retval) return retval;
 
411
        }
355
412
        execv(file, argv);
356
413
        perror("execv");
357
414
        exit(errno);
390
447
    }
391
448
    return (int) status;
392
449
}
 
450
bool process_exists(HANDLE h) {
 
451
    unsigned long status=1;
 
452
    if (GetExitCodeProcess(h, &status)) {
 
453
        if (status == STILL_ACTIVE) return true;
 
454
    }
 
455
    return false;
 
456
}
 
457
 
393
458
#else
394
459
int get_exit_status(int pid) {
395
460
    int status;
396
461
    waitpid(pid, &status, 0);
397
462
    return status;
398
463
}
 
464
bool process_exists(int pid) {
 
465
    int p = waitpid(pid, 0, WNOHANG);
 
466
    if (p == pid) return false;     // process has exited
 
467
    if (p == -1) return false;      // PID doesn't exist
 
468
    return true;
 
469
}
399
470
#endif
400
471
 
401
472
#ifdef _WIN32
437
508
    return ERR_ALREADY_RUNNING;
438
509
}
439
510
 
440
 
#ifndef _USING_FCGI_
441
 
#ifndef _WIN32
442
 
// (linux) return current CPU time of the given process
443
 
//
444
 
double linux_cpu_time(int pid) {
445
 
    FILE *file;
446
 
    char file_name[24];
447
 
    unsigned long utime = 0, stime = 0;
448
 
    int n;
449
 
 
450
 
    sprintf(file_name,"/proc/%d/stat",pid);
451
 
    if ((file = fopen(file_name,"r")) != NULL) {
452
 
        n = fscanf(file,"%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%lu%lu",&utime,&stime);
453
 
        fclose(file);
454
 
        if (n != 2) return 0;
455
 
    }
456
 
    return (double)(utime + stime)/100;
457
 
}
458
 
#endif
459
 
#endif
460
 
 
461
 
void boinc_crash() {
462
 
#ifdef _WIN32
463
 
        DebugBreak();
464
 
#else
465
 
        *(int*)0 = 0;
466
 
#endif
467
 
}
468
 
 
469
 
// read file (at most max_len chars, if nonzero) into malloc'd buf
470
 
//
471
 
int read_file_malloc(const char* path, char*& buf, int max_len, bool tail) {
472
 
    FILE* f;
473
 
    int retval, isize;
474
 
    double size;
475
 
 
476
 
    retval = file_size(path, size);
477
 
    if (retval) return retval;
478
 
 
479
 
    f = fopen(path, "r");
480
 
    if (!f) return ERR_FOPEN;
481
 
 
482
 
    if (max_len && size > max_len) {
483
 
        if (tail) {
484
 
            fseek(f, (long)size-max_len, SEEK_SET);
485
 
        }
486
 
        size = max_len;
487
 
    }
488
 
    isize = (int) size;
489
 
    buf = (char*)malloc(isize+1);
490
 
    size_t n = fread(buf, 1, isize, f);
491
 
    buf[n] = 0;
492
 
    fclose(f);
493
 
    return 0;
494
 
}
495
 
 
496
 
// read file (at most max_len chars, if nonzero) into string
497
 
//
498
 
int read_file_string(const char* path, string& result, int max_len, bool tail) {
499
 
    result.erase();
500
 
    int retval;
501
 
    char* buf;
502
 
 
503
 
    retval = read_file_malloc(path, buf, max_len, tail);
504
 
    if (retval) return retval;
505
 
    result = buf;
506
 
    free(buf);
507
 
    return 0;
508
 
}
509
 
 
510
 
const char *BOINC_RCSID_ab65c90e1e = "$Id: util.C 13901 2007-10-18 08:56:44Z charlief $";
 
511
const char *BOINC_RCSID_ab65c90e1e = "$Id: util.C 15038 2008-04-10 16:42:09Z romw $";