/* * Process input from the socket connecting the mpiexec process to the * child process. * * The return status is interpreted by the IOLoop code in ioloop.c ; * a zero is a normal exit. */ int PMIServHandleInput(int fd, int rdwr, void *extra) { PMIProcess *pentry = (PMIProcess *) extra; int rc; int returnCode = 0; char inbuf[PMIU_MAXLINE], cmd[MAXPMICMD]; PMICmdMap *p; int cmdtype; DBG_PRINTFCOND(pmidebug, ("Handling PMI input\n")); if ((rc = PMIUBufferedReadLine(pentry, inbuf, PMIU_MAXLINE)) > 0) { DBG_PRINTFCOND(pmidebug, ("Entering PMIServHandleInputFd %s\n", inbuf)); PMIU_parse_keyvals(inbuf); cmdtype = PMIGetCommand(cmd, sizeof(cmd)); DBG_PRINTFCOND(pmidebug, ("cmd = %s\n", cmd)); /* Look for the command and execute the related function */ p = pmiCommands; while (p->handler) { if (strncmp(cmd, p->cmdName, MAXPMICMD) == 0) { rc = (p->handler) (pentry); break; } p++; } if (!p->handler) { PMIU_printf(1, "unknown cmd %s\n", cmd); } } else { /* lost contact with client */ DBG_PRINTFCOND(pmidebug, ("EOF on PMI input\n")); /* returning a 1 causes the IO loop code to close the socket */ returnCode = 1; } return returnCode; }
/* Implement the singleton init handshake. See the discussion in simplepmi.c for the protocol */ int PMI_InitSingletonConnection(int fd, PMIProcess * pmiprocess) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; int rc; char version[PMIU_MAXLINE], subversion[PMIU_MAXLINE]; /* We start with the singinit command, wait for the singinit from * the client, and then send the singinit_info */ MPL_snprintf(buf, PMIU_MAXLINE, "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=no authtype=none\n", PMI_VERSION, PMI_SUBVERSION); PMIWriteLine(fd, buf); PMIReadLine(fd, buf, PMIU_MAXLINE); PMIU_parse_keyvals(buf); PMIU_getval("cmd", cmd, MAXPMICMD); if (strcmp(cmd, "singinit")) { PMIU_printf(1, "Unexpected cmd %s\n", cmd); return -1; } /* Could look at authtype */ /* check version compatibility with PMI client library */ PMIU_getval("pmi_version", version, PMIU_MAXLINE); PMIU_getval("pmi_subversion", subversion, PMIU_MAXLINE); if (PMI_VERSION == atoi(version) && PMI_SUBVERSION >= atoi(subversion)) rc = 0; else rc = -1; MPL_snprintf(buf, PMIU_MAXLINE, "cmd=singinit_info versionok=%s stdio=no kvsname=%s\n", (rc == 0) ? "yes" : "no", (char *) (pmiprocess->group->kvs->kvsname)); PMIWriteLine(fd, buf); return 0; }
/* * This is a special routine. It accepts the first input from the * remote process, and returns the PMI_ID value. -1 is returned on error */ int PMI_Init_port_connection(int fd) { char message[PMIU_MAXLINE], cmd[MAXPMICMD]; int pmiid = -1; DBG_PRINTFCOND(pmidebug, ("Beginning initial handshake read\n")); PMIReadLine(fd, message, PMIU_MAXLINE); DBG_PRINTFCOND(pmidebug, ("received message %s\n", message)); PMIU_parse_keyvals(message); PMIU_getval("cmd", cmd, MAXPMICMD); if (strcmp(cmd, "initack")) { PMIU_printf(1, "Unexpected cmd %s, expected initack\n", cmd); return -1; } PMIU_getval("pmiid", cmd, MAXPMICMD); pmiid = atoi(cmd); return pmiid; }
int PMI_Init( int *spawned ) { char *p; int notset = 1; int rc; PMI_initialized = PMI_UNINITIALIZED; /* FIXME: Why is setvbuf commented out? */ /* FIXME: What if the output should be fully buffered (directed to file)? unbuffered (user explicitly set?) */ /* setvbuf(stdout,0,_IONBF,0); */ setbuf(stdout,NULL); /* PMIU_printf( 1, "PMI_INIT\n" ); */ /* Get the value of PMI_DEBUG from the environment if possible, since we may have set it to help debug the setup process */ p = getenv( "PMI_DEBUG" ); if (p) PMI_debug = atoi( p ); /* Get the fd for PMI commands; if none, we're a singleton */ rc = getPMIFD(¬set); if (rc) { return rc; } if ( PMI_fd == -1 ) { /* Singleton init: Process not started with mpiexec, so set size to 1, rank to 0 */ PMI_size = 1; PMI_rank = 0; *spawned = 0; PMI_initialized = SINGLETON_INIT_BUT_NO_PM; /* 256 is picked as the minimum allowed length by the PMI servers */ PMI_kvsname_max = 256; PMI_keylen_max = 256; PMI_vallen_max = 256; return( 0 ); } /* If size, rank, and debug are not set from a communication port, use the environment */ if (notset) { if ( ( p = getenv( "PMI_SIZE" ) ) ) PMI_size = atoi( p ); else PMI_size = 1; if ( ( p = getenv( "PMI_RANK" ) ) ) { PMI_rank = atoi( p ); /* Let the util routine know the rank of this process for any messages (usually debugging or error) */ PMIU_Set_rank( PMI_rank ); } else PMI_rank = 0; if ( ( p = getenv( "PMI_DEBUG" ) ) ) PMI_debug = atoi( p ); else PMI_debug = 0; /* Leave unchanged otherwise, which indicates that no value was set */ } /* FIXME: Why does this depend on their being a port??? */ /* FIXME: What is this for? */ #ifdef USE_PMI_PORT if ( ( p = getenv( "PMI_TOTALVIEW" ) ) ) PMI_totalview = atoi( p ); if ( PMI_totalview ) { char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE]; /* FIXME: This should use a cmd/response rather than a expecting the server to set a value in this and only this case */ /* FIXME: And it most ceratainly should not happen *before* the initialization handshake */ PMIU_readline( PMI_fd, buf, PMIU_MAXLINE ); PMIU_parse_keyvals( buf ); PMIU_getval( "cmd", cmd, PMIU_MAXLINE ); if ( strncmp( cmd, "tv_ready", PMIU_MAXLINE ) != 0 ) { PMIU_printf( 1, "expecting cmd=tv_ready, got %s\n", buf ); return( PMI_FAIL ); } } #endif PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max ); /* FIXME: This is something that the PM should tell the process, rather than deliver it through the environment */ if ( ( p = getenv( "PMI_SPAWNED" ) ) ) PMI_spawned = atoi( p ); else PMI_spawned = 0; if (PMI_spawned) *spawned = 1; else *spawned = 0; if ( ! PMI_initialized ) PMI_initialized = NORMAL_INIT_WITH_PM; return( 0 ); }