mirror of https://github.com/BOINC/boinc.git
- Second pass at the above. We still need run_program() in util.C.
The problem was that there's a lot of extra stuff needed for running apps on Windows (e.g. related to sandboxing). This needed to be a new function. svn path=/trunk/boinc/; revision=14879
This commit is contained in:
parent
cc2f1a20a0
commit
671524df2a
|
@ -2179,3 +2179,18 @@ David Mar 10 2008
|
||||||
util.C,h
|
util.C,h
|
||||||
sched/
|
sched/
|
||||||
server_types.C,h
|
server_types.C,h
|
||||||
|
|
||||||
|
David Mar 10 2008
|
||||||
|
- Second pass at the above. We still need run_program() in util.C.
|
||||||
|
The problem was that there's a lot of extra stuff needed
|
||||||
|
for running apps on Windows (e.g. related to sandboxing).
|
||||||
|
This needed to be a new function.
|
||||||
|
|
||||||
|
clientgui/
|
||||||
|
MainDocument.cpp
|
||||||
|
clientscr/
|
||||||
|
screensaver.cpp
|
||||||
|
lib/
|
||||||
|
Makefile.am
|
||||||
|
proc_control.C,h
|
||||||
|
util.C,h
|
||||||
|
|
|
@ -1257,12 +1257,11 @@ int CMainDocument::WorkShowGraphics(RESULT* result)
|
||||||
argv[0] = "--graphics";
|
argv[0] = "--graphics";
|
||||||
argv[1] = 0;
|
argv[1] = 0;
|
||||||
|
|
||||||
iRetVal = run_program(
|
iRetVal = run_app_windows(
|
||||||
result->slot_path.c_str(),
|
result->slot_path.c_str(),
|
||||||
result->graphics_exec_path.c_str(),
|
result->graphics_exec_path.c_str(),
|
||||||
1,
|
1,
|
||||||
argv,
|
argv,
|
||||||
0,
|
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -175,6 +175,7 @@ int CScreensaver::launch_screensaver(RESULT* rp, int& graphics_application)
|
||||||
argv[0] = "app_graphics"; // not used
|
argv[0] = "app_graphics"; // not used
|
||||||
argv[1] = "--fullscreen";
|
argv[1] = "--fullscreen";
|
||||||
argv[2] = 0;
|
argv[2] = 0;
|
||||||
|
#ifdef _WIN32
|
||||||
retval = run_program(
|
retval = run_program(
|
||||||
rp->slot_path.c_str(),
|
rp->slot_path.c_str(),
|
||||||
rp->graphics_exec_path.c_str(),
|
rp->graphics_exec_path.c_str(),
|
||||||
|
@ -183,6 +184,15 @@ int CScreensaver::launch_screensaver(RESULT* rp, int& graphics_application)
|
||||||
0,
|
0,
|
||||||
graphics_application
|
graphics_application
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
|
retval = run_app_windows(
|
||||||
|
rp->slot_path.c_str(),
|
||||||
|
rp->graphics_exec_path.c_str(),
|
||||||
|
2,
|
||||||
|
argv,
|
||||||
|
graphics_application
|
||||||
|
);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// V5 and Older
|
// V5 and Older
|
||||||
|
|
|
@ -74,7 +74,6 @@ libboinc_a_SOURCES = \
|
||||||
parse.C \
|
parse.C \
|
||||||
prefs.C \
|
prefs.C \
|
||||||
procinfo_unix.C \
|
procinfo_unix.C \
|
||||||
proc_control.C \
|
|
||||||
proxy_info.C \
|
proxy_info.C \
|
||||||
shmem.C \
|
shmem.C \
|
||||||
str_util.C \
|
str_util.C \
|
||||||
|
|
|
@ -17,35 +17,23 @@
|
||||||
// or write to the Free Software Foundation, Inc.,
|
// or write to the Free Software Foundation, Inc.,
|
||||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
// Code used by BOINC components (screensaver, manager, updater)
|
// Code to run a BOINC application (main or graphics) under Windows
|
||||||
// Don't include this in libboinc
|
// Don't include this in applications
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_)
|
#if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_)
|
||||||
#include "boinc_win.h"
|
#include "boinc_win.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "win_util.h"
|
#include "win_util.h"
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "error_numbers.h"
|
#include "error_numbers.h"
|
||||||
#include "common_defs.h"
|
#include "common_defs.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
HANDLE sandbox_account_token = NULL;
|
HANDLE sandbox_account_token = NULL;
|
||||||
PSID sandbox_account_sid = NULL;
|
PSID sandbox_account_sid = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
void get_sandbox_account_token() {
|
void get_sandbox_account_token() {
|
||||||
FILE* f;
|
FILE* f;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
@ -118,17 +106,13 @@ void get_sandbox_account_token() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// Run application, Windows.
|
||||||
// chdir into the given directory, and run a program there.
|
// chdir into the given directory, and run a program there.
|
||||||
// If nsecs is nonzero, make sure it's still running after that many seconds.
|
|
||||||
//
|
|
||||||
// argv is set up Unix-style, i.e. argv[0] is the program name
|
// argv is set up Unix-style, i.e. argv[0] is the program name
|
||||||
//
|
//
|
||||||
|
int run_app_windows(
|
||||||
#ifdef _WIN32
|
const char* dir, const char* file, int argc, char *const argv[], HANDLE& id
|
||||||
int run_program(
|
|
||||||
const char* dir, const char* file, int argc, char *const argv[], double nsecs, HANDLE& id
|
|
||||||
) {
|
) {
|
||||||
int retval;
|
int retval;
|
||||||
PROCESS_INFORMATION process_info;
|
PROCESS_INFORMATION process_info;
|
||||||
|
@ -235,125 +219,6 @@ int run_program(
|
||||||
return -1; // CreateProcess returns 1 if successful, false if it failed.
|
return -1; // CreateProcess returns 1 if successful, false if it failed.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsecs) {
|
|
||||||
boinc_sleep(nsecs);
|
|
||||||
if (GetExitCodeProcess(process_info.hProcess, &status)) {
|
|
||||||
if (status != STILL_ACTIVE) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id = process_info.hProcess;
|
id = process_info.hProcess;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
int run_program(
|
|
||||||
const char* dir, const char* file, int , char *const argv[], double nsecs, int& id
|
|
||||||
) {
|
|
||||||
int retval;
|
|
||||||
int pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
if (dir) {
|
|
||||||
retval = chdir(dir);
|
|
||||||
if (retval) return retval;
|
|
||||||
}
|
|
||||||
execv(file, argv);
|
|
||||||
perror("execv");
|
|
||||||
exit(errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsecs) {
|
|
||||||
boinc_sleep(3);
|
|
||||||
if (waitpid(pid, 0, WNOHANG) == pid) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
id = pid;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
void kill_program(HANDLE pid) {
|
|
||||||
TerminateProcess(pid, 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void kill_program(int pid) {
|
|
||||||
kill(pid, SIGKILL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
int get_exit_status(HANDLE pid_handle) {
|
|
||||||
unsigned long status=1;
|
|
||||||
while (1) {
|
|
||||||
if (GetExitCodeProcess(pid_handle, &status)) {
|
|
||||||
if (status == STILL_ACTIVE) {
|
|
||||||
boinc_sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (int) status;
|
|
||||||
}
|
|
||||||
bool process_exists(HANDLE h) {
|
|
||||||
unsigned long status=1;
|
|
||||||
if (GetExitCodeProcess(h, &status)) {
|
|
||||||
if (status == STILL_ACTIVE) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
int get_exit_status(int pid) {
|
|
||||||
int status;
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
bool process_exists(int pid) {
|
|
||||||
int p = waitpid(pid, 0, WNOHANG);
|
|
||||||
if (p == pid) return false; // process has exited
|
|
||||||
if (p == -1) return false; // PID doesn't exist
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static int get_client_mutex(const char*) {
|
|
||||||
char buf[MAX_PATH] = "";
|
|
||||||
|
|
||||||
// Global mutex on Win2k and later
|
|
||||||
//
|
|
||||||
if (IsWindows2000Compatible()) {
|
|
||||||
strcpy(buf, "Global\\");
|
|
||||||
}
|
|
||||||
strcat( buf, RUN_MUTEX);
|
|
||||||
|
|
||||||
HANDLE h = CreateMutex(NULL, true, buf);
|
|
||||||
if ((h==0) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
|
|
||||||
return ERR_ALREADY_RUNNING;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static int get_client_mutex(const char* dir) {
|
|
||||||
char path[1024];
|
|
||||||
static FILE_LOCK file_lock;
|
|
||||||
|
|
||||||
sprintf(path, "%s/%s", dir, LOCK_FILE_NAME);
|
|
||||||
if (file_lock.lock(path)) {
|
|
||||||
return ERR_ALREADY_RUNNING;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wait_client_mutex(const char* dir, double timeout) {
|
|
||||||
double start = dtime();
|
|
||||||
while (1) {
|
|
||||||
int retval = get_client_mutex(dir);
|
|
||||||
if (!retval) return 0;
|
|
||||||
boinc_sleep(1);
|
|
||||||
if (dtime() - start > timeout) break;
|
|
||||||
}
|
|
||||||
return ERR_ALREADY_RUNNING;
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,21 +4,6 @@ extern HANDLE sandbox_account_token;
|
||||||
extern PSID sandbox_account_sid;
|
extern PSID sandbox_account_sid;
|
||||||
extern void get_sandbox_account_token();
|
extern void get_sandbox_account_token();
|
||||||
|
|
||||||
extern int run_program(
|
extern int run_app_windows(
|
||||||
const char* path, const char* cdir, int argc, char *const argv[], double, HANDLE&
|
const char* path, const char* cdir, int argc, char *const argv[], HANDLE&
|
||||||
);
|
);
|
||||||
|
|
||||||
extern void kill_program(HANDLE);
|
|
||||||
extern int get_exit_status(HANDLE);
|
|
||||||
extern bool process_exists(HANDLE);
|
|
||||||
|
|
||||||
#else
|
|
||||||
extern int run_program(
|
|
||||||
const char* path, const char* cdir, int argc, char *const argv[], double, int&
|
|
||||||
);
|
|
||||||
extern void kill_program(int);
|
|
||||||
extern int get_exit_status(int);
|
|
||||||
extern bool process_exists(int);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int wait_client_mutex(const char* dir, double timeout);
|
|
||||||
|
|
171
lib/util.C
171
lib/util.C
|
@ -30,8 +30,11 @@
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#endif
|
#endif
|
||||||
|
@ -338,4 +341,172 @@ int read_file_string(const char* path, string& result, int max_len, bool tail) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chdir into the given directory, and run a program there.
|
||||||
|
// If nsecs is nonzero, make sure it's still running after that many seconds.
|
||||||
|
//
|
||||||
|
// argv is set up Unix-style, i.e. argv[0] is the program name
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int run_program(
|
||||||
|
const char* dir, const char* file, int argc, char *const argv[], double nsecs, HANDLE& id
|
||||||
|
) {
|
||||||
|
int retval;
|
||||||
|
PROCESS_INFORMATION process_info;
|
||||||
|
STARTUPINFO startup_info;
|
||||||
|
char cmdline[1024];
|
||||||
|
char error_msg[1024];
|
||||||
|
unsigned long status;
|
||||||
|
|
||||||
|
memset(&process_info, 0, sizeof(process_info));
|
||||||
|
memset(&startup_info, 0, sizeof(startup_info));
|
||||||
|
startup_info.cb = sizeof(startup_info);
|
||||||
|
|
||||||
|
strcpy(cmdline, "");
|
||||||
|
for (int i=0; i<argc; i++) {
|
||||||
|
strcat(cmdline, argv[i]);
|
||||||
|
if (i<argc-1) {
|
||||||
|
strcat(cmdline, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = CreateProcess(
|
||||||
|
file,
|
||||||
|
cmdline,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
dir,
|
||||||
|
&startup_info,
|
||||||
|
&process_info
|
||||||
|
);
|
||||||
|
if (!retval) {
|
||||||
|
windows_error_string(error_msg, sizeof(error_msg));
|
||||||
|
fprintf(stderr, "CreateProcess failed: '%s'\n", error_msg);
|
||||||
|
return -1; // CreateProcess returns 1 if successful, false if it failed.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsecs) {
|
||||||
|
boinc_sleep(nsecs);
|
||||||
|
if (GetExitCodeProcess(process_info.hProcess, &status)) {
|
||||||
|
if (status != STILL_ACTIVE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id = process_info.hProcess;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int run_program(
|
||||||
|
const char* dir, const char* file, int , char *const argv[], double nsecs, int& id
|
||||||
|
) {
|
||||||
|
int retval;
|
||||||
|
int pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
if (dir) {
|
||||||
|
retval = chdir(dir);
|
||||||
|
if (retval) return retval;
|
||||||
|
}
|
||||||
|
execv(file, argv);
|
||||||
|
perror("execv");
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nsecs) {
|
||||||
|
boinc_sleep(3);
|
||||||
|
if (waitpid(pid, 0, WNOHANG) == pid) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id = pid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
void kill_program(HANDLE pid) {
|
||||||
|
TerminateProcess(pid, 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void kill_program(int pid) {
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int get_exit_status(HANDLE pid_handle) {
|
||||||
|
unsigned long status=1;
|
||||||
|
while (1) {
|
||||||
|
if (GetExitCodeProcess(pid_handle, &status)) {
|
||||||
|
if (status == STILL_ACTIVE) {
|
||||||
|
boinc_sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int) status;
|
||||||
|
}
|
||||||
|
bool process_exists(HANDLE h) {
|
||||||
|
unsigned long status=1;
|
||||||
|
if (GetExitCodeProcess(h, &status)) {
|
||||||
|
if (status == STILL_ACTIVE) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int get_exit_status(int pid) {
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
bool process_exists(int pid) {
|
||||||
|
int p = waitpid(pid, 0, WNOHANG);
|
||||||
|
if (p == pid) return false; // process has exited
|
||||||
|
if (p == -1) return false; // PID doesn't exist
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static int get_client_mutex(const char*) {
|
||||||
|
char buf[MAX_PATH] = "";
|
||||||
|
|
||||||
|
// Global mutex on Win2k and later
|
||||||
|
//
|
||||||
|
if (IsWindows2000Compatible()) {
|
||||||
|
strcpy(buf, "Global\\");
|
||||||
|
}
|
||||||
|
strcat( buf, RUN_MUTEX);
|
||||||
|
|
||||||
|
HANDLE h = CreateMutex(NULL, true, buf);
|
||||||
|
if ((h==0) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
|
||||||
|
return ERR_ALREADY_RUNNING;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int get_client_mutex(const char* dir) {
|
||||||
|
char path[1024];
|
||||||
|
static FILE_LOCK file_lock;
|
||||||
|
|
||||||
|
sprintf(path, "%s/%s", dir, LOCK_FILE_NAME);
|
||||||
|
if (file_lock.lock(path)) {
|
||||||
|
return ERR_ALREADY_RUNNING;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wait_client_mutex(const char* dir, double timeout) {
|
||||||
|
double start = dtime();
|
||||||
|
while (1) {
|
||||||
|
int retval = get_client_mutex(dir);
|
||||||
|
if (!retval) return 0;
|
||||||
|
boinc_sleep(1);
|
||||||
|
if (dtime() - start > timeout) break;
|
||||||
|
}
|
||||||
|
return ERR_ALREADY_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
const char *BOINC_RCSID_ab65c90e1e = "$Id$";
|
const char *BOINC_RCSID_ab65c90e1e = "$Id$";
|
||||||
|
|
20
lib/util.h
20
lib/util.h
|
@ -75,4 +75,24 @@ extern void boinc_crash();
|
||||||
extern int read_file_malloc(const char* path, char*&, int max_len=0, bool tail=false);
|
extern int read_file_malloc(const char* path, char*&, int max_len=0, bool tail=false);
|
||||||
extern int read_file_string(const char* path, std::string&, int max_len=0, bool tail=false);
|
extern int read_file_string(const char* path, std::string&, int max_len=0, bool tail=false);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
extern int run_program(
|
||||||
|
const char* path, const char* cdir, int argc, char *const argv[], double, HANDLE&
|
||||||
|
);
|
||||||
|
|
||||||
|
extern void kill_program(HANDLE);
|
||||||
|
extern int get_exit_status(HANDLE);
|
||||||
|
extern bool process_exists(HANDLE);
|
||||||
|
|
||||||
|
#else
|
||||||
|
extern int run_program(
|
||||||
|
const char* path, const char* cdir, int argc, char *const argv[], double, int&
|
||||||
|
);
|
||||||
|
extern void kill_program(int);
|
||||||
|
extern int get_exit_status(int);
|
||||||
|
extern bool process_exists(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int wait_client_mutex(const char* dir, double timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue