// exit handler: really only meant to handle exits() called by GLUT... // void restart() { // don't do anything except when exit is called from the graphics-thread if (!pthread_equal(pthread_self(), graphics_thread)) { if (debug) fprintf(stderr, "exit() was called from worker-thread\n"); return; } if (debug) fprintf(stderr, "restart: exit() called from graphics-thread.\n"); // if we are standalone and glut was initialized, // we assume user pressed 'close', and we exit the app // // if (glut_is_initialized ) { if (boinc_is_standalone()) { if (debug) fprintf(stderr, "Assuming user pressed 'close'... means we're exiting now.\n" ); if (boinc_delete_file(LOCKFILE) != 0) { perror ("Failed to remove lockfile..\n"); } return; } } // re-install the exit-handler to catch glut's notorious exits()... // atexit(restart); // jump back to entry-point in xwin_graphics_event_loop(); // if (debug) fprintf(stderr, "restart: Jumping back to event_loop.\n"); longjmp(jbuf, JUMP_EXIT); }
void win_graphics_event_loop() { MSG msg; // Get platform information // OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); is_windows_9x = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); // Register window class and graphics mode message // reg_win_class(); gfx_timer_id = SetTimer(NULL, 1, 30, (TIMERPROC)&timer_handler); if (boinc_is_standalone()) { set_mode(MODE_WINDOW); } else { set_mode(MODE_HIDE_GRAPHICS); } while (1) { if (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { break; } } unreg_win_class(); SetEvent(hQuitEvent); // Signal the worker thread that we're quitting }
static PyObject *boinc_boinc_is_standalone(PyObject *self, PyObject *args) { int isItStandalone; isItStandalone = boinc_is_standalone(); return Py_BuildValue("i", isItStandalone); }
// Generate a unique virtual machine name for a given task instance // Rules: // 1. Must be unique // 2. Must identifity itself as being part of BOINC // 3. Must be file system compatible // int virtualbox_generate_vm_name( std::string& name ) { APP_INIT_DATA aid; boinc_get_init_data_p( &aid ); name.empty(); name = "boinc_"; if (boinc_is_standalone()) { name += "standalone"; } else { name += aid.wu_name; } if (!name.empty()) { return 1; } return 0; }
// Generate a deterministic yet unique UUID for a given medium (hard drive, // cd drive, hard drive image) // Rules: // 1. Must be unique // 2. Must identifity itself as being part of BOINC // 3. Must be based on the slot directory id // 4. Must be in the form of a GUID // 00000000-0000-0000-0000-000000000000 // // Form/Meaning // A B C D E // 00000000-0000-0000-0000-000000000000 // // A = Drive ID // B = Slot ID // C = Standalone Flag // D = Reserved // E = 'BOINC' ASCII converted to Hex // int virtualbox_generate_medium_uuid( int drive_id, std::string& uuid ) { APP_INIT_DATA aid; TCHAR medium_uuid[256]; boinc_get_init_data_p( &aid ); sprintf( medium_uuid, _T("%08d-%04d-%04d-0000-00424F494E43"), drive_id, aid.slot, boinc_is_standalone() ); uuid = medium_uuid; if (!uuid.empty()) { return 1; } return 0; }
void qcnTrickleUp(const char* strTrickle, const int iVariety, const char* strWU) { // probably not thread safe, but within a same proc/thread (i.e. main.cpp) we should not have trickles/triggers sent within a second because BOINC // can't handle them that fast (i.e. writes out a trickle file name with a timestamp to the nearest second, and trickles within a second // write over each other static double dTimeLastTrickle = 0.0; // set time trickle sent so we can pause if necessary #ifdef QCNLIVE return; // no trickles on gui! #else // just a "sanity check" to make sure we haven't sent too many trickles in a row (i.e. > 1 sec) //trickleup::qcnCheckTrickleSleep(); double dCurTime = dtime(); if ((dCurTime - dTimeLastTrickle) < 1.0) { // last trickle sent less than a second ago, which would be bad for boinc, so sleep a bit) boinc_sleep((dCurTime - dTimeLastTrickle) + .10); } char strVariety[32]; memset(strVariety, 0x00, 32); strcpy(strVariety, "trigger"); switch (iVariety) { case TRIGGER_VARIETY_FINALSTATS: strcpy(strVariety, "finalstats"); break; case TRIGGER_VARIETY_QUAKELIST: strcpy(strVariety, "quakelist"); break; case TRIGGER_VARIETY_NORMAL: strcpy(strVariety, "trigger"); break; case TRIGGER_VARIETY_PING: strcpy(strVariety, "ping"); break; case TRIGGER_VARIETY_CONTINUAL: strcpy(strVariety, "continual"); break; } // BOINC adds the appropriate workunit/resultid etc and posts to trickle_up table in MySQL static bool bInHere = false; if (bInHere) return; bInHere = true; // CMC let's print out trickles in standalone mode so I can see something! if (boinc_is_standalone()) { char szTFile[32]; static unsigned long iNum = 0L; iNum++; sprintf(szTFile, "trickle_%09lu_%s.xml", (unsigned long) iNum, strVariety); FILE* fTrickle = boinc_fopen(szTFile, "w"); if (fTrickle) { fwrite(strTrickle, 1, strlen(strTrickle), fTrickle); fclose(fTrickle); } } else { boinc_send_trickle_up((char*) strVariety, (char*) strTrickle); } bInHere = false; #endif dTimeLastTrickle = dtime(); // set time trickle sent so we can pause if necessary }
// graphics thread main-function // NOTE: this should only be called *ONCE* by an application // void xwin_graphics_event_loop() { int restarted = 0; if (debug) fprintf(stderr, "Direct call to xwin_graphics_event_loop()\n"); struct sigaction sa = {0}; memset(&sa, 0, sizeof(sa)); sa.sa_handler = restart_sig; sa.sa_flags = SA_RESTART; // install signal handler to catch abort() from GLUT. Note that // signal handlers are global to ALL threads, so the signal // handler that we record here in &original_signal_handler is the // previous one that applied to BOTH threads if (sigaction(SIGABRT, &sa, &original_signal_handler)) { perror("unable to install signal handler to catch SIGABORT"); } // handle glut's notorious exits().. atexit(restart); // THIS IS THE re-entry point at exit or ABORT in the graphics-thread restarted = setjmp(jbuf); // if we came here from an ABORT-signal thrown in this thread, // we put this thread to sleep // if (restarted == JUMP_ABORT) { while(1) { sleep(1); } } // If using freeglut, check to see if we need to // reinitialize glut and graphics. // We're only resetting flags here, actual reinit function // is called in make_new_window(). // if (glut_is_initialized && glut_is_freeglut) { if (1 == (glut_is_initialized = FREEGLUT_IS_INITIALIZED)) { if (!GLUT_HAVE_WINDOW) { win = 0; } } } if (boinc_is_standalone()) { if (restarted) { while(1) { sleep(1); // assuming glutInit() failed: put graphics-thread to sleep } } else { // open the graphics-window set_mode(MODE_WINDOW); glutTimerFunc(TIMER_INTERVAL_MSEC, timer_handler, 0); } } else { if (!glut_is_initialized) { #ifdef __APPLE__ setMacPList(); #endif set_mode(MODE_HIDE_GRAPHICS); while ( current_graphics_mode == MODE_HIDE_GRAPHICS ) { if (debug) fprintf(stderr, "Graphics-thread now waiting for client-message...\n" ); wait_for_initial_message(); if (debug) fprintf(stderr, "got a graphics-message from client... \n"); timer_handler(0); } } else // here glut has been initialized previously // probably the user pressed window-'close' // set_mode(MODE_HIDE_GRAPHICS); // close any previously open windows } // ok we should be ready & initialized by now to call glutMainLoop() // if (debug) fprintf(stderr, "now calling glutMainLoop()...\n"); glutMainLoop(); if (debug) fprintf(stderr, "glutMainLoop() returned!! This should never happen...\n"); }
// message handler (includes timer, Windows msgs) // LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam // Additional Message Information ) { switch(uMsg) { case WM_ERASEBKGND: // Check To See If Windows Is Trying To Erase The Background return 0; case WM_KEYDOWN: if(!window_ready) return 0; if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } else { boinc_app_key_press((int)wParam, (int)lParam); } return 0; case WM_KEYUP: if(!window_ready) return 0; if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } else { boinc_app_key_release((int)wParam, (int)lParam); } return 0; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: if(!window_ready) return 0; if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } else { int which; bool down; POINT cPos; GetCursorPos(&cPos); parse_mouse_event(uMsg, which, down); boinc_app_mouse_button(cPos.x, cPos.y, which, down); } return 0; case WM_MOUSEMOVE: if(!window_ready) return 0; POINT cPos; GetCursorPos(&cPos); if (current_graphics_mode == MODE_FULLSCREEN) { if(cPos.x != mousePos.x || cPos.y != mousePos.y) { set_mode(MODE_HIDE_GRAPHICS); } } else { boinc_app_mouse_move( cPos.x, cPos.y, (wParam&MK_LBUTTON)!=0, (wParam&MK_MBUTTON)!=0, (wParam&MK_RBUTTON)!=0 ); } return 0; case WM_CLOSE: if (boinc_is_standalone()) { boinc_exit(0); } else { if (current_graphics_mode != MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } } return 0; case WM_POWERBROADCAST: if (PBT_APMSUSPEND == wParam) { set_mode(MODE_HIDE_GRAPHICS); suspend_activities(); return TRUE; } if (PBT_APMQUERYSUSPENDFAILED == wParam || PBT_APMRESUMESUSPEND == wParam) { set_mode(acked_graphics_mode); restore_activities(); return TRUE; } if (PBT_APMQUERYSUSPEND == wParam) { return TRUE; } break; case WM_PAINT: PAINTSTRUCT ps; RECT winRect; HDC pdc; if (!graphics_threadh) graphics_threadh=(HANDLE)GetCurrentThreadId(); pdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &winRect); FillRect(pdc, &winRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); EndPaint(hWnd, &ps); return 0; case WM_SIZE: if ( SIZE_MINIMIZED == wParam ) { visible = FALSE; } else { visible = TRUE; } if(!window_ready) return 0; app_graphics_resize(LOWORD(lParam), HIWORD(lParam)); return 0; case WM_SHUTDOWNGFX: set_mode(MODE_HIDE_GRAPHICS); return 0; default: if ( WM_BOINCSFW == uMsg ) { SetForegroundWindow(hWnd); } } // Pass All Unhandled Messages To DefWindowProc return DefWindowProc(hWnd,uMsg,wParam,lParam); }
// switch to the given graphics mode. This is called: // - on initialization // - when get mode change msg (via shared mem) // - when in SS mode and get user input // static void set_mode(int mode) { int new_mode = mode; GRAPHICS_MSG current_desktop; if (mode == current_graphics_mode) return; if (current_graphics_mode != MODE_FULLSCREEN) { if (IsIconic(hWnd) || IsZoomed(hWnd)){ // If graphics window is minimized or maximized // then set default values of window size rect.left = 50; rect.top = 50; rect.right = 50+640; rect.bottom = 50+480; } else GetWindowRect(hWnd, &rect); // else get current values } KillWindow(); // Detect our current desktop and window station. memset(current_desktop.window_station, 0, sizeof(current_desktop.window_station)/sizeof(char)); memset(current_desktop.desktop, 0, sizeof(current_desktop.desktop)/sizeof(char)); if (!is_windows_9x) { GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, current_desktop.window_station, (sizeof(current_desktop.window_station) / sizeof(char)), NULL ); GetUserObjectInformation( GetThreadDesktop(GetCurrentThreadId()), UOI_NAME, current_desktop.desktop, (sizeof(current_desktop.desktop) / sizeof(char)), NULL ); } if (!is_windows_9x && !boinc_is_standalone() && strlen(graphics_msg.window_station) > 0 && strlen(graphics_msg.desktop) > 0 && (strcmp(current_desktop.window_station, graphics_msg.window_station) || strcmp(current_desktop.desktop, graphics_msg.desktop))) { BOINCINFO("Checking Desktop and Window Station Parameters\n"); GetDesktopWindow(); if (NULL == hOriginalWindowStation) { hOriginalWindowStation = GetProcessWindowStation(); if (NULL == hOriginalWindowStation) { BOINCINFO("Failed to retrieve the orginal window station\n"); } } if (NULL == hOriginalDesktop) { hOriginalDesktop = GetThreadDesktop(GetCurrentThreadId()); if (NULL == hOriginalDesktop) { BOINCINFO("Failed to retrieve the orginal desktop\n"); } } hInteractiveWindowStation = OpenWindowStation( graphics_msg.window_station, FALSE, GENERIC_READ ); if (NULL == hInteractiveWindowStation) { BOINCINFO("Failed to retrieve the required window station\n"); new_mode = MODE_UNSUPPORTED; } else { BOINCINFO("Retrieved the required window station\n"); if (!SetProcessWindowStation(hInteractiveWindowStation)) { BOINCINFO("Failed to SetProcessWindowStation (GLE: '%d')\n", GetLastError()); } hInteractiveDesktop = OpenDesktop( graphics_msg.desktop, (DWORD)NULL, FALSE, GENERIC_READ | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU ); if (NULL == hInteractiveDesktop) { BOINCINFO("Failed to retrieve the required desktop\n"); new_mode = MODE_UNSUPPORTED; } else { BOINCINFO("Retrieved the required desktop\n"); if (!SetThreadDesktop(hInteractiveDesktop)) { BOINCINFO("Failed to SetThreadDesktop (GLE: '%d')\n", GetLastError()); } } } } current_graphics_mode = new_mode; if (new_mode != MODE_HIDE_GRAPHICS && new_mode != MODE_UNSUPPORTED) { make_new_window(); } }
int DC_initClient(void) { char path[PATH_MAX], *buf, label[32]; int i, ret; FILE *f; /* We leave the redirection to BOINC and only copy stdout.txt/stderr.txt * to the final output location in DC_finishClient(). This means BOINC * can rotate the files so they won't grow too big. */ if (boinc_init_diagnostics(BOINC_DIAG_REDIRECTSTDERR | BOINC_DIAG_REDIRECTSTDOUT)) return DC_ERR_INTERNAL; if (boinc_init()) return DC_ERR_INTERNAL; /* Parse the config file if the master sent one */ buf = DC_resolveFileName(DC_FILE_IN, DC_CONFIG_FILE); if (buf) { ret = _DC_parseCfg(buf); if (ret && ret != DC_ERR_SYSTEM) return ret; } free(buf); /* Check if we are starting from a checkpoint file */ if ((f = boinc_fopen(LAST_CKPT_FILE, "r"))) { fgets(path, sizeof(path), f); fclose(f); if (strlen(path)) last_complete_ckpt = strdup(path); } /* If the application did not generate a checkpoint file before, check * if the master sent one */ else last_complete_ckpt = DC_resolveFileName(DC_FILE_IN, CKPT_LABEL_IN); if (last_complete_ckpt) DC_log(LOG_INFO, "Found initial checkpoint file %s", last_complete_ckpt); /* Extract the WU name from init_data.xml */ if (boinc_is_standalone()) { DC_log(LOG_NOTICE, "Running in stand-alone mode, some " "functions are not available"); wu_name[0] = '\0'; } else { APP_INIT_DATA init_data; boinc_get_init_data(init_data); strncpy(wu_name, init_data.wu_name, sizeof(wu_name)); } /* Initialize all optional output files as empty to prevent * <file_xfer_error>s */ for (i = 0; i < DC_getMaxSubresults(); i++) { snprintf(label, sizeof(label), "%s%d", SUBRESULT_PFX, i); if (boinc_resolve_filename(label, path, sizeof(path))) continue; f = boinc_fopen(path, "w"); if (f) fclose(f); } ret = boinc_resolve_filename(CKPT_LABEL_OUT, path, sizeof(path)); if (!ret) { f = boinc_fopen(path, "w"); if (f) fclose(f); } DC_log(LOG_INFO, "DC-API initialized for work unit %s", wu_name); return 0; }
void boinc_is_standalone_(int* result) { *result = boinc_is_standalone(); }