📄 labview_test_controller.cpp
字号:
// $Id: labview_test_controller.cpp 79540 2007-08-30 17:34:50Z shuston $//// Defines the entry point for the LabVIEW RT test controller DLL application.// This DLL is loaded at system boot by LabVIEW RT. The controller waits for// TCP connections from the ACE+TAO test scripts. The test scripts will direct// operation of the tests via commands sent over TCP. In order to be ready for// connections without intervention via VI, the initial load will spawn a// thread that sets up the listening socket.#include "stdafx.h"#include <errno.h>#include <fcntl.h>#include <io.h>#include <memory.h>#include <process.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <Winsock2.h>// NULL is the documented way to check DLL handles, and this is plain// Windows code, not ACE, so we stick to the Microsoft way...// FUZZ: disable check_for_NULL// TEST_FUNC is the prototype for the called test's main entrypoint. It's// the normal C main.typedef int (*TEST_FUNC) (int argc, char *argv[]);// Thread entrypointsstatic unsigned int __stdcall test_control (void *param);static unsigned int __stdcall peer_svc (void *peer_p);static unsigned int __stdcall run_test (void *test_p);static const char *format_errmsg (unsigned int errcode, const char *prefix);// Logging informationstatic const char *LogName = "acetao.log";static HANDLE logf = INVALID_HANDLE_VALUE;BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ if (ul_reason_for_call == DLL_PROCESS_ATTACH) { return (0 != _beginthreadex (0, // security 8 * 1024, // stack size test_control, // entrypoint 0, // param 0, // creation flags 0)); // ptr to thread id } return TRUE;}class Test{public: Test () : dll_handle_ (NULL), thr_handle_ (0), entry_ (0), running_ (false), status_ (-1) {} ~Test (); HANDLE handle (void) { return this->thr_handle_; } int run (void); const char *start (const char *name); bool status (int *exit_status); int wait (void); void kill (void); // Clean up remnants of a test run. void cleanup (void);private: HMODULE dll_handle_; HANDLE thr_handle_; TEST_FUNC entry_; bool running_; int status_; enum { CMDLINE_LEN = 1024, ARGV_SIZE = 100 }; char name_[CMDLINE_LEN]; char cmdline_[CMDLINE_LEN]; int argc_; char *argv_[ARGV_SIZE];};class Peer{public: Peer (SOCKET h) : handle_ (h) {} // Run the Peer's session; intended to be called from a new thread devoted // to this peer's session. int svc (void);private: Peer () {}; // Process command input from socket. int command (void); // Send a reply string to the peer. int reply (const char *msg); SOCKET handle_; Test test_;};// Run a peer session; assume there's a thread for each session, so this// object has all it needs for context located in 'this' object, and it can// block at any point as long as one remembers that there is one or more// test threads running and some attention must be paid to the encapsulated// socket handle over which this object receives control commands from the// host test driver.intPeer::svc (void){ // Read commands until EOF (peer closed) or protocol error while (0 == this->command ()) ; closesocket (this->handle_); this->handle_ = INVALID_SOCKET; return 0;}intPeer::command (void){ // The protocol exchanges with the peer are execpted to be lock-step // request-reply command lines, so we can make assumptions about a complete // line being available to make life easier. const int MAX_RECV = 1024; char line[MAX_RECV], *p; p = &line[0]; int count = 0, len = 0; while ((count = recv (this->handle_, p, MAX_RECV - len, 0)) > 0) { p[count] = '\0'; len += count; p += count; char *nl; if ((nl = strchr (line, '\n')) == 0) continue; // At this point we have a 0-terminated string with a newline ending // the command line. Break out and process the command. break; } if (count <= 0) return -1; // Relay closed/error socket to caller char *cmd = strtok (line, "\t \n\r"); if (cmd == 0) { char err[1024]; sprintf (err, "Can't parse input: %s\n", line); this->reply (err); return -1; } // Which command is it? These commands are known: // // run <test-dll> [args] // Run test in the named test-dll; respond with "OK" or an error string. // status // If test still running return "RUNNING" else return exit status. // wait // Wait for test to exit; return "OK" // kill // Kill the thread with the most recent test; return "OK". // snaplog // Take a snapshot of the current stdout/stderr log to a new file // name and reset the stdout/stderr log. if (strcmp ("run", cmd) == 0) { char *test = strtok (0, "\t \n\r"); if (test == 0) { this->reply ("Malformed run command\n"); return -1; } // start() pulls apart the rest of the command line... const char *errmsg = this->test_.start (test); if (errmsg == 0) this->reply ("OK\n"); else this->reply (errmsg); } else if (strcmp ("status", cmd) == 0) { int status; if (this->test_.status (&status)) { char retvalmsg[64]; sprintf (retvalmsg, "%d\n", status); this->reply (retvalmsg); } else this->reply ("RUNNING\n"); } else if (strcmp ("wait", cmd) == 0) { int status = this->test_.wait (); char retvalmsg[64]; sprintf (retvalmsg, "%d\n", status); this->reply (retvalmsg); } else if (strcmp ("kill", cmd) == 0) { // Killing things is bad... say we can't and the host should reboot us. this->reply ("NO - please reboot me\n"); } else if (strcmp ("waitforfile", cmd) == 0) { char *name = strtok (0, "\t \n\r"); if (name == 0) { this->reply ("Malformed waitforfile command\n"); return -1; } char *secs_s = strtok (0, "\t \n\r"); int secs = 0; if (secs_s == 0 || (secs = atoi (secs_s)) <= 0) { this->reply ("Malformed waitforfile command\n"); return -1; } struct _stat info; const char *msg = 0; bool found = false; while (secs > 0) { if (_stat (name, &info) == -1) // No file yet { if (errno != ENOENT) { // Something more serious than no file yet; bail out. msg = format_errmsg (errno, name); break; } } else { if (info.st_size > 0) { found = true; break; } } // Either no file yet, or it's there but with no content yet. Sleep (1 * 1000); // arg is in msec --secs; } if (found) this->reply ("OK\n"); else if (secs == 0) this->reply ("TIMEOUT\n"); else this->reply (msg); } else if (strcmp ("snaplog", cmd) == 0) { if (logf == INVALID_HANDLE_VALUE) { this->reply ("NONE\n"); } else { CloseHandle (logf); if (0 == rename (LogName, "snapshot.txt")) { char abspath[1024]; if (_fullpath (abspath, "snapshot.txt", 1024)) { strcat (abspath, "\n"); this->reply (abspath); } else { // Last ditch effort to get a name back to the client this->reply ("\\ni-rt\\system\\snapshot.txt\n"); } } else { this->reply ("NONE\n"); } // Reset stdout/stderr to a new file logf = CreateFile (LogName, FILE_ALL_ACCESS, FILE_SHARE_READ,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -