1
0
mirror of https://github.com/simh/simh.git synced 2026-01-26 04:01:38 +00:00

FRONTPANEL: Added better protocol debug support to debug simulator startup issues

This commit is contained in:
Mark Pizzolato
2015-02-26 11:28:08 -08:00
parent df6953bf82
commit 71fe58b33a
4 changed files with 135 additions and 64 deletions

View File

@@ -188,84 +188,98 @@ static unsigned char mantra[] = {
TN_IAC, TN_DO, TN_BIN
};
static void *
_panel_malloc (size_t size)
{
void *p = malloc (size);
if (p == NULL)
sim_panel_set_error ("Out of Memory");
return p;
}
static void _panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
{
if (p && p->Debug && (dbits & p->debug)) {
int i;
struct timespec time_now;
va_list arglist;
char timestamp[32];
size_t obufsize = 10240 + 8*bufsize;
char *obuf = (char *)_panel_malloc (obufsize);
clock_gettime(CLOCK_REALTIME, &time_now);
fprintf(p->Debug, "%lld.%03d ", (long long)(time_now.tv_sec), (int)(time_now.tv_nsec/1000000));
sprintf (timestamp, "%lld.%03d ", (long long)(time_now.tv_sec), (int)(time_now.tv_nsec/1000000));
va_start (arglist, bufsize);
vfprintf (p->Debug, fmt, arglist);
vsnprintf (obuf, obufsize - 1, fmt, arglist);
va_end (arglist);
for (i=0; i<bufsize; ++i) {
switch ((unsigned char)buf[i]) {
case TN_CR:
fprintf(p->Debug, "_TN_CR_");
sprintf (&obuf[strlen (obuf)], "_TN_CR_");
break;
case TN_LF:
fprintf(p->Debug, "_TN_LF_");
sprintf (&obuf[strlen (obuf)], "_TN_LF_");
break;
case TN_IAC:
fprintf(p->Debug, "_TN_IAC_");
sprintf (&obuf[strlen (obuf)], "_TN_IAC_");
switch ((unsigned char)buf[i+1]) {
case TN_IAC:
fprintf(p->Debug, "_TN_IAC_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_IAC_"); ++i;
break;
case TN_DONT:
fprintf(p->Debug, "_TN_DONT_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_DONT_"); ++i;
break;
case TN_DO:
fprintf(p->Debug, "_TN_DO_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_DO_"); ++i;
break;
case TN_WONT:
fprintf(p->Debug, "_TN_WONT_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_WONT_"); ++i;
break;
case TN_WILL:
fprintf(p->Debug, "_TN_WILL_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_WILL_"); ++i;
break;
default:
fprintf(p->Debug, "_0x%02X_", (unsigned char)buf[i+1]); ++i;
sprintf (&obuf[strlen (obuf)], "_0x%02X_", (unsigned char)buf[i+1]); ++i;
break;
}
switch ((unsigned char)buf[i+1]) {
case TN_BIN:
fprintf(p->Debug, "_TN_BIN_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_BIN_"); ++i;
break;
case TN_ECHO:
fprintf(p->Debug, "_TN_ECHO_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_ECHO_"); ++i;
break;
case TN_SGA:
fprintf(p->Debug, "_TN_SGA_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_SGA_"); ++i;
break;
case TN_LINE:
fprintf(p->Debug, "_TN_LINE_"); ++i;
sprintf (&obuf[strlen (obuf)], "_TN_LINE_"); ++i;
break;
default:
fprintf(p->Debug, "_0x%02X_", (unsigned char)buf[i+1]); ++i;
sprintf (&obuf[strlen (obuf)], "_0x%02X_", (unsigned char)buf[i+1]); ++i;
break;
}
break;
default:
if (isprint((u_char)buf[i]))
fprintf(p->Debug, "%c", buf[i]);
sprintf (&obuf[strlen (obuf)], "%c", buf[i]);
else {
fprintf(p->Debug, "_");
sprintf (&obuf[strlen (obuf)], "_");
if ((buf[i] >= 1) && (buf[i] <= 26))
fprintf(p->Debug, "^%c", 'A' + buf[i] - 1);
sprintf (&obuf[strlen (obuf)], "^%c", 'A' + buf[i] - 1);
else
fprintf(p->Debug, "\\%03o", (u_char)buf[i]);
fprintf(p->Debug, "_");
sprintf (&obuf[strlen (obuf)], "\\%03o", (u_char)buf[i]);
sprintf (&obuf[strlen (obuf)], "_");
}
break;
}
}
fprintf(p->Debug, "\n");
fprintf(p->Debug, "%s%s\n", timestamp, obuf);
free (obuf);
}
}
@@ -294,16 +308,6 @@ if (panel->Debug)
}
static void *
_panel_malloc (size_t size)
{
void *p = malloc (size);
if (p == NULL)
sim_panel_set_error ("Out of Memory");
return p;
}
static int
_panel_send (PANEL *p, const char *msg, int len)
{
@@ -446,6 +450,15 @@ sim_panel_start_simulator (const char *sim_path,
const char *sim_config,
size_t device_panel_count)
{
return sim_panel_start_simulator_debug (sim_path, sim_config, device_panel_count, NULL);
}
PANEL *
sim_panel_start_simulator_debug (const char *sim_path,
const char *sim_config,
size_t device_panel_count,
const char *debug_file)
{
PANEL *p = NULL;
FILE *fIn = NULL;
FILE *fOut = NULL;
@@ -528,6 +541,11 @@ fprintf (fOut, "set remote -u telnet=%s\n", hostport);
fprintf (fOut, "set remote master\n");
fclose (fOut);
fOut = NULL;
if (debug_file) {
sim_panel_set_debug_file (p, debug_file);
sim_panel_set_debug_mode (p, DBG_XMT|DBG_RCV);
_panel_debug (p, DBG_XMT|DBG_RCV, "Creating Simulator Process %s\n", NULL, 0, sim_path);
}
if (1) {
#if defined(_WIN32)
char cmd[2048];
@@ -553,7 +571,8 @@ if (1) {
#else
p->pidProcess = fork();
if (p->pidProcess == 0) {
close (0); close (1); close (2); /* make sure not to pass the open standard handles */
close (0); close (1); close (2); /* make sure not to pass the open standard handles */
dup (dup (open ("/dev/null", O_RDWR))); /* open standard handles to /dev/null */
if (execlp (sim_path, sim_path, p->temp_config, NULL, NULL)) {
perror ("execl");
exit(errno);
@@ -574,17 +593,25 @@ for (i=0; i<100; i++) { /* Allow up to 10 seconds waiting for simulator
break;
}
if (p->sock == INVALID_SOCKET) {
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
if (stat (sim_path, &statb) < 0)
sim_panel_set_error ("Can't stat simulator '%s': %s", sim_path, strerror(errno));
else
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
goto Error_Return;
}
strcpy (p->hostport, hostport);
_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator at %s after %dms\n", NULL, 0, hostport, i*100);
pthread_mutex_init (&p->io_lock, NULL);
pthread_mutex_init (&p->io_send_lock, NULL);
pthread_cond_init (&p->io_done, NULL);
pthread_cond_init (&p->startup_cond, NULL);
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return;
}
if (1) {
pthread_attr_t attr;
pthread_mutex_init (&p->io_lock, NULL);
pthread_mutex_init (&p->io_send_lock, NULL);
pthread_cond_init (&p->io_done, NULL);
pthread_cond_init (&p->startup_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_mutex_lock (&p->io_lock);
@@ -595,10 +622,6 @@ if (1) {
pthread_mutex_unlock (&p->io_lock);
pthread_cond_destroy (&p->startup_cond);
}
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return;
}
if (device_panel_count) {
p->devices = (PANEL **)_panel_malloc (device_panel_count*sizeof(*p->devices));
if (p->devices == NULL)
@@ -606,8 +629,7 @@ if (device_panel_count) {
memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
p->device_count = device_panel_count;
}
msleep (1000);
/* Validate existence of requested register */
/* Validate sim_frontpanel API version */
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r")) {
goto Error_Return;
}
@@ -634,7 +656,15 @@ if (fOut) {
}
if (buf)
free (buf);
sim_panel_destroy (p);
if (1) {
const char *err = sim_panel_get_error();
char *errbuf = (char *)_panel_malloc (1 + strlen (err));
strcpy (errbuf, err); /* preserve error info while closing */
sim_panel_destroy (p);
sim_panel_set_error ("%s", errbuf);
free (errbuf);
}
return NULL;
}
@@ -666,7 +696,7 @@ if (p->device_name == NULL)
strcpy (p->device_name, device_name);
p->parent = simulator_panel;
p->sock = INVALID_SOCKET;
for (i=0; i<5; i++) {
for (i=0; i<100; i++) {
p->sock = sim_connect_sock_ex (NULL, simulator_panel->hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
if (p->sock == INVALID_SOCKET)
msleep (100);
@@ -678,13 +708,17 @@ if (p->sock == INVALID_SOCKET) {
goto Error_Return;
}
strcpy (p->hostport, simulator_panel->hostport);
pthread_mutex_init (&p->io_lock, NULL);
pthread_mutex_init (&p->io_send_lock, NULL);
pthread_cond_init (&p->io_done, NULL);
pthread_cond_init (&p->startup_cond, NULL);
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return;
}
if (1) {
pthread_attr_t attr;
pthread_mutex_init (&p->io_lock, NULL);
pthread_mutex_init (&p->io_send_lock, NULL);
pthread_cond_init (&p->io_done, NULL);
pthread_cond_init (&p->startup_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_mutex_lock (&p->io_lock);
@@ -695,10 +729,6 @@ if (1) {
pthread_mutex_unlock (&p->io_lock);
pthread_cond_destroy (&p->startup_cond);
}
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return;
}
simulator_panel->devices[device_num] = p;
_panel_register_panel (p);
return p;
@@ -1069,6 +1099,28 @@ pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
pthread_mutex_lock (&p->io_lock);
if (!p->parent) {
while (1) {
int new_data = sim_read_sock (p->sock, &buf[buf_data], sizeof(buf)-(buf_data+1));
if (new_data <= 0) {
sim_panel_set_error ("%s", sim_get_err_sock("Unexpected socket read"));
_panel_debug (p, DBG_RCV, "%s", NULL, 0, sim_panel_get_error());
p->State = Error;
break;
}
_panel_debug (p, DBG_RCV, "Startup receive of %d bytes: ", &buf[buf_data], new_data, new_data);
buf_data += new_data;
buf[buf_data] = '\0';
if ((size_t)buf_data < strlen (sim_prompt))
continue;
if (!strcmp (sim_prompt, &buf[buf_data - strlen (sim_prompt)])) {
memmove (buf, &buf[buf_data - strlen (sim_prompt)], strlen (sim_prompt) + 1);
buf_data = strlen (sim_prompt);
break;
}
}
}
p->io_thread_running = 1;
pthread_cond_signal (&p->startup_cond); /* Signal we're ready to go */
while ((p->sock != INVALID_SOCKET) &&