mirror of https://github.com/BOINC/boinc.git
Merge pull request #4141 from BOINC/dpa_graphics_exec2
Check graphics app before telling GUI about it
This commit is contained in:
commit
ba3702e8c8
|
@ -759,6 +759,10 @@ int ACTIVE_TASK::write_gui(MIOFILE& fout) {
|
|||
(fd - first_fraction_done)/(elapsed_time - first_fraction_done_elapsed_time)
|
||||
);
|
||||
}
|
||||
|
||||
// only report a graphics app if file exists and we can execute it
|
||||
//
|
||||
app_version->check_graphics_exec();
|
||||
if (strlen(app_version->graphics_exec_path)) {
|
||||
fout.printf(
|
||||
" <graphics_exec_path>%s</graphics_exec_path>\n"
|
||||
|
@ -767,6 +771,7 @@ int ACTIVE_TASK::write_gui(MIOFILE& fout) {
|
|||
slot_path
|
||||
);
|
||||
}
|
||||
|
||||
if (strlen(web_graphics_url)) {
|
||||
fout.printf(
|
||||
" <web_graphics_url>%s</web_graphics_url>\n",
|
||||
|
|
|
@ -15,17 +15,6 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/fat.h>
|
||||
#include <mach/machine.h>
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
extern int compareOSVersionTo(int toMajor, int toMinor);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "boinc_win.h"
|
||||
#else
|
||||
|
@ -1325,17 +1314,7 @@ int CLIENT_STATE::link_app_version(PROJECT* p, APP_VERSION* avp) {
|
|||
}
|
||||
|
||||
if (!strcmp(file_ref.open_name, GRAPHICS_APP_FILENAME)) {
|
||||
char relpath[MAXPATHLEN], path[MAXPATHLEN];
|
||||
get_pathname(fip, relpath, sizeof(relpath));
|
||||
relative_to_absolute(relpath, path);
|
||||
#ifdef __APPLE__
|
||||
if (can_run_on_this_CPU(path))
|
||||
|
||||
#endif
|
||||
{
|
||||
safe_strcpy(avp->graphics_exec_path, path);
|
||||
safe_strcpy(avp->graphics_exec_file, fip->name);
|
||||
}
|
||||
avp->graphics_exec_fip = fip;
|
||||
}
|
||||
|
||||
// any file associated with an app version must be signed
|
||||
|
@ -2373,125 +2352,3 @@ bool CLIENT_STATE::abort_sequence_done() {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
union headeru {
|
||||
fat_header fat;
|
||||
mach_header mach;
|
||||
};
|
||||
// Get the architecture of this computer's CPU: x86_64 or arm64.
|
||||
// Read the executable file's mach-o headers to determine the
|
||||
// architecture(s) of its code.
|
||||
// Returns 1 if application can run natively on this computer,
|
||||
// else returns 0.
|
||||
//
|
||||
// ToDo: determine whether x86_64 graphics apps emulated on arm64 Macs
|
||||
// properly run under Rosetta 2. Note: years ago, PowerPC apps emulated
|
||||
// by Rosetta on i386 Macs crashed when running graphics.
|
||||
//
|
||||
|
||||
int CLIENT_STATE::can_run_on_this_CPU(char* exec_path) {
|
||||
FILE *f;
|
||||
int retval = 0;
|
||||
|
||||
headeru myHeader;
|
||||
fat_arch fatHeader;
|
||||
|
||||
static bool x86_64_CPU = false;
|
||||
static bool arm64_cpu = false;
|
||||
static bool need_CPU_architecture = true;
|
||||
uint32_t n, i, len;
|
||||
uint32_t theMagic;
|
||||
integer_t file_architecture;
|
||||
|
||||
if (need_CPU_architecture) {
|
||||
// Determine the architecture of the CPU we are running on
|
||||
// ToDo: adjust this code accordingly.
|
||||
uint32_t cputype = 0;
|
||||
size_t size = sizeof (cputype);
|
||||
int res = sysctlbyname ("hw.cputype", &cputype, &size, NULL, 0);
|
||||
if (res) return false; // Should never happen
|
||||
// Since we require MacOS >= 10.7, the CPU must be x86_64 or arm64
|
||||
x86_64_CPU = ((cputype &0xff) == CPU_TYPE_X86);
|
||||
arm64_cpu = ((cputype &0xff) == CPU_TYPE_ARM);
|
||||
|
||||
need_CPU_architecture = false;
|
||||
}
|
||||
|
||||
f = boinc_fopen(exec_path, "rb");
|
||||
if (!f) {
|
||||
return retval; // Should never happen
|
||||
}
|
||||
|
||||
myHeader.fat.magic = 0;
|
||||
myHeader.fat.nfat_arch = 0;
|
||||
|
||||
fread(&myHeader, 1, sizeof(fat_header), f);
|
||||
theMagic = myHeader.mach.magic;
|
||||
switch (theMagic) {
|
||||
case MH_CIGAM:
|
||||
case MH_MAGIC:
|
||||
case MH_MAGIC_64:
|
||||
case MH_CIGAM_64:
|
||||
file_architecture = myHeader.mach.cputype;
|
||||
if ((theMagic == MH_CIGAM) || (theMagic == MH_CIGAM_64)) {
|
||||
file_architecture = OSSwapInt32(file_architecture);
|
||||
}
|
||||
if (x86_64_CPU && (file_architecture == CPU_TYPE_I386)) {
|
||||
// Single-architecture i386 file on x86_64 CPU
|
||||
if (compareOSVersionTo(10, 15) < 0) { // OS >= 10.15 are 64-bit only
|
||||
retval = 1;
|
||||
}
|
||||
} else
|
||||
if (x86_64_CPU && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = 1; // Single-architecture x86_64 file on x86_64 CPU
|
||||
} else
|
||||
if (arm64_cpu && (file_architecture == CPU_TYPE_ARM64)) {
|
||||
retval = 1; // Single-architecture arm64 file on arm64 CPU
|
||||
} else
|
||||
if (arm64_cpu && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = 1; // Single-architecture x86_64 file emulated on arm64 CPU
|
||||
// ToDo: determine whether emulated graphics apps work properly
|
||||
}
|
||||
break;
|
||||
case FAT_MAGIC:
|
||||
case FAT_CIGAM:
|
||||
n = myHeader.fat.nfat_arch;
|
||||
if (theMagic == FAT_CIGAM) {
|
||||
n = OSSwapInt32(myHeader.fat.nfat_arch);
|
||||
}
|
||||
// Multiple architecture (fat) file
|
||||
for (i=0; i<n; i++) {
|
||||
len = fread(&fatHeader, 1, sizeof(fat_arch), f);
|
||||
if (len < sizeof(fat_arch)) {
|
||||
break; // Should never happen
|
||||
}
|
||||
file_architecture = fatHeader.cputype;
|
||||
if (theMagic == FAT_CIGAM) {
|
||||
file_architecture = OSSwapInt32(file_architecture);
|
||||
}
|
||||
|
||||
if (x86_64_CPU && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = 1; // file with x86_64 architecture on x86_64 CPU
|
||||
break;
|
||||
} else
|
||||
if (arm64_cpu && (file_architecture == CPU_TYPE_ARM64)) {
|
||||
retval = 1; // file with arm64 architecture on arm64 CPU
|
||||
break;
|
||||
} else
|
||||
if (arm64_cpu && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = 1; // file with x86_64 architecture emulated on arm64 CPU
|
||||
// ToDo: determine whether emulated graphics apps work properly
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -296,10 +296,6 @@ struct CLIENT_STATE {
|
|||
void clear_absolute_times();
|
||||
void set_now();
|
||||
void log_show_projects();
|
||||
#ifdef __APPLE__
|
||||
// Check whether the app can run on this CPU architecture
|
||||
int can_run_on_this_CPU(char* exec_path);
|
||||
#endif
|
||||
|
||||
// --------------- cpu_sched.cpp:
|
||||
double total_resource_share();
|
||||
|
|
|
@ -780,6 +780,7 @@ void APP_VERSION::init() {
|
|||
app = NULL;
|
||||
project = NULL;
|
||||
ref_cnt = 0;
|
||||
graphics_exec_fip = NULL;
|
||||
safe_strcpy(graphics_exec_path,"");
|
||||
safe_strcpy(graphics_exec_file, "");
|
||||
max_working_set_size = 0;
|
||||
|
@ -1039,6 +1040,37 @@ bool APP_VERSION::api_version_at_least(int major, int minor) {
|
|||
return min >= minor;
|
||||
}
|
||||
|
||||
// If app version has a graphics program,
|
||||
// see whether the exec is present and can be run.
|
||||
// If so fill in the file name and path.
|
||||
// Called from GUI RPC handler.
|
||||
//
|
||||
void APP_VERSION::check_graphics_exec() {
|
||||
if (!graphics_exec_fip) return;
|
||||
if (strlen(graphics_exec_path)) return;
|
||||
if (graphics_exec_fip->status < 0) {
|
||||
// download or verify of graphics exec failed; don't check again
|
||||
//
|
||||
graphics_exec_fip = NULL;
|
||||
return;
|
||||
}
|
||||
if (graphics_exec_fip->status != FILE_PRESENT) return;
|
||||
|
||||
char relpath[MAXPATHLEN], path[MAXPATHLEN];
|
||||
get_pathname(graphics_exec_fip, relpath, sizeof(relpath));
|
||||
relative_to_absolute(relpath, path);
|
||||
#ifdef __APPLE__
|
||||
if (!can_run_on_this_CPU(path)) {
|
||||
// if can't run this exec, don't check again
|
||||
//
|
||||
graphics_exec_fip = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
safe_strcpy(graphics_exec_path, path);
|
||||
safe_strcpy(graphics_exec_file, graphics_exec_fip->name);
|
||||
}
|
||||
|
||||
int FILE_REF::parse(XML_PARSER& xp) {
|
||||
bool temp;
|
||||
|
||||
|
|
|
@ -296,6 +296,8 @@ struct GPU_USAGE {
|
|||
double usage;
|
||||
};
|
||||
|
||||
// if you add anything, initialize it in init()
|
||||
//
|
||||
struct APP_VERSION {
|
||||
char app_name[256];
|
||||
int version_num;
|
||||
|
@ -317,8 +319,14 @@ struct APP_VERSION {
|
|||
PROJECT* project;
|
||||
std::vector<FILE_REF> app_files;
|
||||
int ref_cnt;
|
||||
|
||||
// graphics app, if any
|
||||
// the strings are filled in after exec is downloaded and verified
|
||||
//
|
||||
FILE_INFO *graphics_exec_fip;
|
||||
char graphics_exec_path[MAXPATHLEN];
|
||||
char graphics_exec_file[256];
|
||||
|
||||
double max_working_set_size;
|
||||
// max working set of tasks using this app version.
|
||||
// unstarted jobs using this app version are assumed
|
||||
|
@ -361,6 +369,7 @@ struct APP_VERSION {
|
|||
inline bool is_opencl() {
|
||||
return (strstr(plan_class, "opencl") != NULL);
|
||||
}
|
||||
void check_graphics_exec();
|
||||
};
|
||||
|
||||
struct WORKUNIT {
|
||||
|
|
|
@ -124,6 +124,14 @@ using std::min;
|
|||
#include <IOKit/IOKitLib.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/fat.h>
|
||||
#include <mach/machine.h>
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
extern int compareOSVersionTo(int toMajor, int toMinor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -1988,3 +1996,122 @@ long HOST_INFO::user_idle_time(bool check_all_logins) {
|
|||
}
|
||||
|
||||
#endif // ! __APPLE__
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
union headeru {
|
||||
fat_header fat;
|
||||
mach_header mach;
|
||||
};
|
||||
// Get the architecture of this computer's CPU: x86_64 or arm64.
|
||||
// Read the executable file's mach-o headers to determine the
|
||||
// architecture(s) of its code.
|
||||
// Returns 1 if application can run natively on this computer,
|
||||
// else returns 0.
|
||||
//
|
||||
// ToDo: determine whether x86_64 graphics apps emulated on arm64 Macs
|
||||
// properly run under Rosetta 2. Note: years ago, PowerPC apps emulated
|
||||
// by Rosetta on i386 Macs crashed when running graphics.
|
||||
//
|
||||
|
||||
bool can_run_on_this_CPU(char* exec_path) {
|
||||
FILE *f;
|
||||
int retval = false;
|
||||
|
||||
headeru myHeader;
|
||||
fat_arch fatHeader;
|
||||
|
||||
static bool x86_64_CPU = false;
|
||||
static bool arm64_cpu = false;
|
||||
static bool need_CPU_architecture = true;
|
||||
uint32_t n, i, len;
|
||||
uint32_t theMagic;
|
||||
integer_t file_architecture;
|
||||
|
||||
if (need_CPU_architecture) {
|
||||
// Determine the architecture of the CPU we are running on
|
||||
// ToDo: adjust this code accordingly.
|
||||
uint32_t cputype = 0;
|
||||
size_t size = sizeof (cputype);
|
||||
int res = sysctlbyname ("hw.cputype", &cputype, &size, NULL, 0);
|
||||
if (res) return false; // Should never happen
|
||||
// Since we require MacOS >= 10.7, the CPU must be x86_64 or arm64
|
||||
x86_64_CPU = ((cputype &0xff) == CPU_TYPE_X86);
|
||||
arm64_cpu = ((cputype &0xff) == CPU_TYPE_ARM);
|
||||
|
||||
need_CPU_architecture = false;
|
||||
}
|
||||
|
||||
f = boinc_fopen(exec_path, "rb");
|
||||
if (!f) {
|
||||
return retval; // Should never happen
|
||||
}
|
||||
|
||||
myHeader.fat.magic = 0;
|
||||
myHeader.fat.nfat_arch = 0;
|
||||
|
||||
fread(&myHeader, 1, sizeof(fat_header), f);
|
||||
theMagic = myHeader.mach.magic;
|
||||
switch (theMagic) {
|
||||
case MH_CIGAM:
|
||||
case MH_MAGIC:
|
||||
case MH_MAGIC_64:
|
||||
case MH_CIGAM_64:
|
||||
file_architecture = myHeader.mach.cputype;
|
||||
if ((theMagic == MH_CIGAM) || (theMagic == MH_CIGAM_64)) {
|
||||
file_architecture = OSSwapInt32(file_architecture);
|
||||
}
|
||||
if (x86_64_CPU && (file_architecture == CPU_TYPE_I386)) {
|
||||
// Single-architecture i386 file on x86_64 CPU
|
||||
if (compareOSVersionTo(10, 15) < 0) {
|
||||
// OS >= 10.15 are 64-bit only
|
||||
retval = true;
|
||||
}
|
||||
} else if (x86_64_CPU && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = true; // Single-architecture x86_64 file on x86_64 CPU
|
||||
} else if (arm64_cpu && (file_architecture == CPU_TYPE_ARM64)) {
|
||||
retval = true; // Single-architecture arm64 file on arm64 CPU
|
||||
} else if (arm64_cpu && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = true; // Single-architecture x86_64 file emulated on arm64 CPU
|
||||
// TODO: determine whether emulated graphics apps work properly
|
||||
}
|
||||
break;
|
||||
case FAT_MAGIC:
|
||||
case FAT_CIGAM:
|
||||
n = myHeader.fat.nfat_arch;
|
||||
if (theMagic == FAT_CIGAM) {
|
||||
n = OSSwapInt32(myHeader.fat.nfat_arch);
|
||||
}
|
||||
|
||||
// Multiple architecture (fat) file
|
||||
//
|
||||
for (i=0; i<n; i++) {
|
||||
len = fread(&fatHeader, 1, sizeof(fat_arch), f);
|
||||
if (len < sizeof(fat_arch)) {
|
||||
break; // Should never happen
|
||||
}
|
||||
file_architecture = fatHeader.cputype;
|
||||
if (theMagic == FAT_CIGAM) {
|
||||
file_architecture = OSSwapInt32(file_architecture);
|
||||
}
|
||||
|
||||
if (x86_64_CPU && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = true; // file with x86_64 architecture on x86_64 CPU
|
||||
break;
|
||||
} else if (arm64_cpu && (file_architecture == CPU_TYPE_ARM64)) {
|
||||
retval = true; // file with arm64 architecture on arm64 CPU
|
||||
break;
|
||||
} else if (arm64_cpu && (file_architecture == CPU_TYPE_X86_64)) {
|
||||
retval = true; // file with x86_64 architecture emulated on arm64 CPU
|
||||
// TODO: determine whether emulated graphics apps work properly
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -184,7 +184,7 @@ enum BATTERY_STATE {
|
|||
// some output file permanent failure
|
||||
|
||||
// Values of FILE_INFO::status.
|
||||
// If the status is neither of these two,
|
||||
// If the status is none of these,
|
||||
// it's an error code indicating an unrecoverable error
|
||||
// in the transfer of the file,
|
||||
// or that the file was too big and was deleted.
|
||||
|
|
|
@ -150,12 +150,14 @@ public:
|
|||
extern void make_secure_random_string(char*);
|
||||
|
||||
#ifdef _WIN64
|
||||
int get_wsl_information(bool& wsl_available, WSLS& wsls);
|
||||
int get_processor_group(HANDLE);
|
||||
extern int get_wsl_information(bool& wsl_available, WSLS& wsls);
|
||||
extern int get_processor_group(HANDLE);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
int get_system_uptime();
|
||||
extern int get_system_uptime();
|
||||
extern bool can_run_on_this_CPU(char* exec_path);
|
||||
// can the app run on this CPU architecture?
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -165,7 +167,7 @@ extern "C" {
|
|||
#include <IOKit/hidsystem/IOHIDParameter.h>
|
||||
#include <IOKit/hidsystem/event_status_driver.h>
|
||||
|
||||
bool isDualGPUMacBook();
|
||||
extern bool isDualGPUMacBook();
|
||||
|
||||
// Apple has removed NxIdleTime() beginning with OS 10.6, so we must try
|
||||
// loading it at run time to avoid a link error. For details, please see
|
||||
|
|
Loading…
Reference in New Issue