blob: 0ed11d7083af4faec2551235d322289074d18cc9 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly
* marked, so as not to confuse it with the version available from LANL.
*
* Additionally, this program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LA-CC 04-115
******************************************************************************/
#include "config.h"
#include <mpi.h>
#include <getopt.h>
#include <stdlib.h>
#include <stdarg.h>
#include "backend.h"
#include "proxy.h"
#include "proxy_tcp.h"
#define DEFAULT_BACKEND "gdb-mi"
#define DEFAULT_PROXY "tcp"
extern void client(int, int, char *, char *, int);
extern void server(int, int, int, dbg_backend *);
static struct option longopts[] = {
{"debugger", required_argument, NULL, 'b'},
{"debugger_path", required_argument, NULL, 'e'},
{"proxy", required_argument, NULL, 'P'},
{"port", required_argument, NULL, 'p'},
{"host", required_argument, NULL, 'h'},
{"jobid", required_argument, NULL, 'j'},
#ifdef DEBUG
{"debug", optional_argument, NULL, 'd'},
#endif /* DEBUG */
{NULL, 0, NULL, 0}
};
#ifdef DEBUG
static char * shortopts = "b:e:P:p:h:d::";
#else /* DEBUG */
static char * shortopts = "b:e:P:p:h:";
#endif /* DEBUG */
static int fatal_error = 0;
static char *error_str = NULL;
void
error_msg(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vasprintf(&error_str, fmt, ap);
va_end(ap);
fatal_error = 1;
}
void
print_error_msg()
{
if (error_str != NULL) {
fprintf(stderr, "%s", error_str);
fflush(stderr);
}
}
/*
* Main entry point for MPI parallel debugger.
*
* @arg -b debugger select backend debugger
* @arg -e path set backend debugger path
* @arg -p port port number to listen on/connect to
* @arg -h host host to connect to
* @arg -P proxy type of proxy connection to use
* @arg -j jobid jobid of application being debugged
*/
int
main(int argc, char *argv[])
{
int rank;
int size;
int ch;
int jobid = 0;
int port = PROXY_TCP_PORT;
char * host = NULL;
char * debugger_str = DEFAULT_BACKEND;
char * proxy_str = DEFAULT_PROXY;
char * path = NULL;
proxy * p;
dbg_backend * d;
while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
switch (ch) {
case 'b':
debugger_str = optarg;
break;
case 'e':
path = optarg;
break;
case 'P':
proxy_str = optarg;
break;
case 'p':
port = (int)strtol(optarg, NULL, 10);
break;
case 'h':
host = optarg;
break;
case 'j':
jobid = (int)strtol(optarg, NULL, 10);
break;
#ifdef DEBUG
case 'd':
if (optarg == NULL)
debug_level = DEBUG_LEVEL_ALL;
else
debug_level = (int)strtol(optarg, NULL, 10);
break;
#endif /* DEBUG */
default:
error_msg(
"sdm [--debugger=value] [--debugger_path=path]\n"
" [--proxy=proxy]\n"
" [--host=host_name] [--port=port]\n"
" [--jobid=jobid]\n"
#ifdef DEBUG
" [--debug[=level]]\n"
#endif /* DEBUG */
);
goto error_out;
}
argc -= optind;
argv += optind;
if (find_dbg_backend(debugger_str, &d) < 0) {
error_msg("No such backend: \"%s\"\n", debugger_str);
goto error_out;
}
if (path != NULL)
backend_set_path(d, path);
if (find_proxy(proxy_str, &p) < 0) {
error_msg("No such proxy: \"%s\"\n", proxy_str);
goto error_out;
}
/*
* Become an MPI program
*/
error_out:
DEBUG_PRINTS(DEBUG_LEVEL_STARTUP, "starting MPI\n");
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
DEBUG_SET_RANK(rank);
DEBUG_PRINTF(DEBUG_LEVEL_STARTUP, "size=%d rank=%d\n", size, rank);
if (size < 2) {
error_msg("Debugger requires at least 2 processes\n");
}
if (fatal_error) {
if (rank == 0)
print_error_msg();
MPI_Finalize();
return 1;
}
// MPI_Comm_create_errhandler(handle_fatal_errors, &err_handler);
// MPI_Comm_set_errhandler(MPI_COMM_WORLD, err_handler);
/*
* The client process *must* always have task id 'size' - 1 since it
* does not control a debugged process.
*/
if (rank == size-1) {
DEBUG_PRINTS(DEBUG_LEVEL_STARTUP, "starting client\n");
client(size, rank, proxy_str, host, port);
} else {
DEBUG_PRINTF(DEBUG_LEVEL_STARTUP, "starting task %d\n", rank);
server(size, rank, jobid, d);
}
DEBUG_PRINTS(DEBUG_LEVEL_STARTUP, "all finished\n");
MPI_Finalize();
return 0;
}