Commit 1d435ef1 authored by Pavan Balaji's avatar Pavan Balaji
Browse files

[svn-r5962] Clean up the process manager component to move MPICH specific

information to the UI and move generic functionality to utility
functions. Fixed a bug in the MPICH_PORT_RANGE code along the way.
parent 37cf52ef
......@@ -19,6 +19,10 @@ struct HYD_handle {
char *css;
char *rmk;
char *port_range;
char *interface_env_name;
int ckpoint_int;
int print_rank_map;
......@@ -29,13 +33,6 @@ struct HYD_handle {
HYD_status(*stdout_cb) (void *buf, int buflen);
HYD_status(*stderr_cb) (void *buf, int buflen);
/* Timeout (in seconds) is filled in by the UI to be passed to the
* bootstrap server.
*
* FIXME: make this a function parameter.
*/
int timeout;
/* All of the available nodes */
struct HYD_node *node_list;
int global_core_count;
......
......@@ -26,7 +26,7 @@ HYD_status HYD_pmci_launch_procs(void);
*
* Wait for launched processes to complete
*/
HYD_status HYD_pmci_wait_for_completion(void);
HYD_status HYD_pmci_wait_for_completion(int timeout);
/**
* \brief HYD_pmci_finalize - Finalize process management control device
......
......@@ -4,12 +4,14 @@
# See COPYRIGHT in top-level directory.
#
AM_CPPFLAGS += -I$(top_srcdir)/pm/utils
bin_PROGRAMS += pmi_proxy
pmi_proxy_SOURCES = $(top_srcdir)/pm/pmiserv/pmi_proxy.c \
$(top_srcdir)/pm/pmiserv/pmi_proxy_cb.c \
$(top_srcdir)/pm/pmiserv/pmi_proxy_utils.c
pmi_proxy_LDADD = libhydra.a $(external_libs)
pmi_proxy_LDADD = libhydra.a libpm.a $(external_libs)
pmi_proxy_LDFLAGS = $(external_ldflags)
libpm_a_SOURCES += $(top_srcdir)/pm/pmiserv/pmi_handle.c \
......@@ -18,5 +20,4 @@ libpm_a_SOURCES += $(top_srcdir)/pm/pmiserv/pmi_handle.c \
$(top_srcdir)/pm/pmiserv/pmi_handle_v2.c \
$(top_srcdir)/pm/pmiserv/pmi_serv_cb.c \
$(top_srcdir)/pm/pmiserv/pmi_serv_finalize.c \
$(top_srcdir)/pm/pmiserv/pmi_serv_launch.c \
$(top_srcdir)/pm/pmiserv/pmi_serv_utils.c
$(top_srcdir)/pm/pmiserv/pmi_serv_launch.c
......@@ -9,7 +9,7 @@
#include "hydra_base.h"
#include "hydra_utils.h"
#include "pmi_common.h"
#include "pm_utils.h"
struct HYD_pmcd_pmip {
struct HYD_user_global user_global;
......@@ -43,6 +43,7 @@ struct HYD_pmcd_pmip {
/* Proxy details */
struct {
int id;
char *interface_env_name;
char *hostname;
int proxy_core_count;
......
......@@ -14,13 +14,13 @@ struct HYD_pmcd_pmip HYD_pmcd_pmip;
HYD_status HYD_pmcd_pmi_proxy_control_cmd_cb(int fd, HYD_event_t events, void *userp)
{
int cmd_len;
enum HYD_pmcd_pmi_proxy_cmds cmd;
enum HYD_pmu_cmd cmd;
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
/* We got a command from upstream */
status = HYDU_sock_read(fd, &cmd, sizeof(enum HYD_pmcd_pmi_proxy_cmds), &cmd_len,
status = HYDU_sock_read(fd, &cmd, sizeof(enum HYD_pmu_cmd), &cmd_len,
HYDU_SOCK_COMM_MSGWAIT);
HYDU_ERR_POP(status, "error reading command from launcher\n");
if (cmd_len == 0) {
......
......@@ -33,6 +33,7 @@ static HYD_status init_params(void)
HYD_pmcd_pmip.downstream.exit_status = NULL;
HYD_pmcd_pmip.local.id = -1;
HYD_pmcd_pmip.local.interface_env_name = NULL;
HYD_pmcd_pmip.local.hostname = NULL;
HYD_pmcd_pmip.local.proxy_core_count = -1;
HYD_pmcd_pmip.local.proxy_process_count = -1;
......@@ -110,6 +111,9 @@ HYD_status HYD_pmcd_pmi_proxy_cleanup_params(void)
if (HYD_pmcd_pmip.downstream.exit_status)
HYDU_FREE(HYD_pmcd_pmip.downstream.exit_status);
if (HYD_pmcd_pmip.local.interface_env_name)
HYDU_FREE(HYD_pmcd_pmip.local.interface_env_name);
if (HYD_pmcd_pmip.local.hostname)
HYDU_FREE(HYD_pmcd_pmip.local.hostname);
......@@ -263,6 +267,11 @@ static HYD_status version_fn(char *arg, char ***argv)
goto fn_exit;
}
static HYD_status interface_env_name_fn(char *arg, char ***argv)
{
return HYDU_set_str_and_incr(arg, argv, &HYD_pmcd_pmip.local.interface_env_name);
}
static HYD_status hostname_fn(char *arg, char ***argv)
{
return HYDU_set_str_and_incr(arg, argv, &HYD_pmcd_pmip.local.hostname);
......@@ -404,6 +413,7 @@ static struct HYD_arg_match_table match_table[] = {
{"genv-prop", genv_prop_fn, NULL},
{"global-core-count", global_core_count_fn, NULL},
{"version", version_fn, NULL},
{"interface-env-name", interface_env_name_fn, NULL},
{"hostname", hostname_fn, NULL},
{"proxy-core-count", proxy_core_count_fn, NULL},
{"start-pid", start_pid_fn, NULL},
......@@ -494,9 +504,6 @@ static HYD_status parse_exec_params(char **t_argv)
if (HYD_pmcd_pmip.system_global.global_core_count == -1)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "global core count not available\n");
if (HYD_pmcd_pmip.local.hostname == NULL)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "PMI port not available\n");
if (HYD_pmcd_pmip.local.proxy_core_count == -1)
HYDU_ERR_SETANDJUMP(status, HYD_INTERNAL_ERROR, "proxy core count not available\n");
......@@ -695,9 +702,9 @@ HYD_status HYD_pmcd_pmi_proxy_launch_procs(void)
status = HYDU_append_env_to_list(*env, &prop_env);
HYDU_ERR_POP(status, "unable to add env to list\n");
/* Set the MPICH_INTERFACE_HOSTNAME based on what the user provided */
if (HYD_pmcd_pmip.local.hostname) {
status = HYDU_env_create(&env, "MPICH_INTERFACE_HOSTNAME",
/* Set the interface hostname based on what the user provided */
if (HYD_pmcd_pmip.local.hostname && HYD_pmcd_pmip.local.interface_env_name) {
status = HYDU_env_create(&env, HYD_pmcd_pmip.local.interface_env_name,
HYD_pmcd_pmip.local.hostname);
HYDU_ERR_POP(status, "unable to create env\n");
......
......@@ -7,7 +7,7 @@
#ifndef PMI_SERV_H_INCLUDED
#define PMI_SERV_H_INCLUDED
#include "pmi_common.h"
#include "pm_utils.h"
HYD_status HYD_pmcd_pmi_connect_cb(int fd, HYD_event_t events, void *userp);
HYD_status HYD_pmcd_pmi_cmd_cb(int fd, HYD_event_t events, void *userp);
......@@ -17,6 +17,4 @@ HYD_status HYD_pmcd_pmi_serv_cleanup(void);
HYD_status HYD_pmcd_pmi_serv_ckpoint(void);
void HYD_pmcd_pmi_serv_signal_cb(int signal);
HYD_status HYD_pmcd_pmi_send_exec_info(struct HYD_proxy *proxy);
#endif /* PMI_SERV_H_INCLUDED */
......@@ -230,7 +230,7 @@ HYD_status HYD_pmcd_pmi_serv_control_connect_cb(int fd, HYD_event_t events, void
proxy->control_fd = accept_fd;
/* Send out the executable information */
status = HYD_pmcd_pmi_send_exec_info(proxy);
status = HYD_pmu_send_exec_info(proxy);
HYDU_ERR_POP(status, "unable to send exec info to proxy\n");
status = HYDU_dmx_register_fd(1, &accept_fd, HYD_POLLIN, proxy,
......@@ -279,7 +279,7 @@ HYD_status HYD_pmcd_pmi_serv_control_cb(int fd, HYD_event_t events, void *userp)
HYD_status HYD_pmcd_pmi_serv_cleanup(void)
{
struct HYD_proxy *proxy;
enum HYD_pmcd_pmi_proxy_cmds cmd;
enum HYD_pmu_cmd cmd;
HYD_status status = HYD_SUCCESS, overall_status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
......@@ -290,7 +290,7 @@ HYD_status HYD_pmcd_pmi_serv_cleanup(void)
for (proxy = HYD_handle.pg_list.proxy_list; proxy; proxy = proxy->next) {
cmd = KILL_JOB;
status = HYDU_sock_trywrite(proxy->control_fd, &cmd,
sizeof(enum HYD_pmcd_pmi_proxy_cmds));
sizeof(enum HYD_pmu_cmd));
if (status != HYD_SUCCESS) {
HYDU_warn_printf("unable to send data to the proxy on %s\n", proxy->hostname);
overall_status = HYD_INTERNAL_ERROR;
......@@ -307,7 +307,7 @@ HYD_status HYD_pmcd_pmi_serv_cleanup(void)
HYD_status HYD_pmcd_pmi_serv_ckpoint(void)
{
struct HYD_proxy *proxy;
enum HYD_pmcd_pmi_proxy_cmds cmd;
enum HYD_pmu_cmd cmd;
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
......@@ -318,7 +318,7 @@ HYD_status HYD_pmcd_pmi_serv_ckpoint(void)
for (proxy = HYD_handle.pg_list.proxy_list; proxy; proxy = proxy->next) {
cmd = CKPOINT;
status = HYDU_sock_write(proxy->control_fd, &cmd,
sizeof(enum HYD_pmcd_pmi_proxy_cmds));
sizeof(enum HYD_pmu_cmd));
HYDU_ERR_POP(status, "unable to send checkpoint message\n");
}
......@@ -340,12 +340,10 @@ void HYD_pmcd_pmi_serv_signal_cb(int sig)
/* There's nothing we can do with the return value for now. */
HYD_pmcd_pmi_serv_cleanup();
}
else {
if (sig == SIGUSR1) {
HYD_pmcd_pmi_serv_ckpoint();
}
/* Ignore other signals for now */
else if (sig == SIGUSR1) {
HYD_pmcd_pmi_serv_ckpoint();
}
/* Ignore other signals for now */
HYDU_FUNC_EXIT();
return;
......
......@@ -20,21 +20,14 @@ create_and_listen_portstr(HYD_status(*callback) (int fd, HYD_event_t events, voi
char **port_str)
{
int listenfd;
char *port_range, *sport;
char *sport, *port_range;
uint16_t port;
char hostname[MAX_HOSTNAME_LEN];
HYD_status status = HYD_SUCCESS;
/* Check if the user wants us to use a port within a certain
* range. */
port_range = getenv("MPIEXEC_PORTRANGE");
if (!port_range)
port_range = getenv("MPIEXEC_PORT_RANGE");
if (!port_range)
port_range = getenv("MPICH_PORT_RANGE");
/* Listen on a port in the port range */
port = 0;
port_range = HYD_handle.port_range ? HYDU_strdup(HYD_handle.port_range) : NULL;
status = HYDU_sock_listen(&listenfd, port_range, &port);
HYDU_ERR_POP(status, "unable to listen on port\n");
......@@ -148,6 +141,9 @@ static HYD_status fill_in_exec_launch_info(void)
proxy->exec_launch_info[arg++] = HYDU_strdup("--version");
proxy->exec_launch_info[arg++] = HYDU_strdup(HYDRA_VERSION);
proxy->exec_launch_info[arg++] = HYDU_strdup("--interface-env-name");
proxy->exec_launch_info[arg++] = HYDU_strdup(HYD_handle.interface_env_name);
proxy->exec_launch_info[arg++] = HYDU_strdup("--hostname");
proxy->exec_launch_info[arg++] = HYDU_strdup(proxy->node.hostname);
......@@ -332,7 +328,7 @@ HYD_status HYD_pmci_launch_procs(void)
status = create_and_listen_portstr(HYD_pmcd_pmi_serv_control_connect_cb, &control_port);
HYDU_ERR_POP(status, "unable to create PMI port\n");
if (HYD_handle.user_global.debug)
HYDU_dump(stdout, "Got a proxy port string of %s\n", control_port);
HYDU_dump(stdout, "Got a control port string of %s\n", control_port);
status = fill_in_proxy_args(proxy_args);
HYDU_ERR_POP(status, "unable to fill in proxy arguments\n");
......@@ -359,13 +355,13 @@ HYD_status HYD_pmci_launch_procs(void)
}
HYD_status HYD_pmci_wait_for_completion(void)
HYD_status HYD_pmci_wait_for_completion(int timeout)
{
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
status = HYDT_bsci_wait_for_completion(HYD_handle.timeout);
status = HYDT_bsci_wait_for_completion(timeout);
if (status == HYD_TIMED_OUT) {
status = HYD_pmcd_pmi_serv_cleanup();
HYDU_ERR_POP(status, "cleanup of processes failed\n");
......
......@@ -4,4 +4,4 @@
# See COPYRIGHT in top-level directory.
#
libpm_a_SOURCES += $(top_srcdir)/pm/utils/pmi.c
libpm_a_SOURCES += $(top_srcdir)/pm/utils/pm_utils.c
......@@ -6,17 +6,17 @@
#include "hydra.h"
#include "hydra_utils.h"
#include "pmi_serv.h"
#include "pm_utils.h"
HYD_status HYD_pmcd_pmi_send_exec_info(struct HYD_proxy *proxy)
HYD_status HYD_pmu_send_exec_info(struct HYD_proxy *proxy)
{
enum HYD_pmcd_pmi_proxy_cmds cmd;
enum HYD_pmu_cmd cmd;
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
cmd = PROC_INFO;
status = HYDU_sock_write(proxy->control_fd, &cmd, sizeof(enum HYD_pmcd_pmi_proxy_cmds));
status = HYDU_sock_write(proxy->control_fd, &cmd, sizeof(enum HYD_pmu_cmd));
HYDU_ERR_POP(status, "unable to write data to proxy\n");
status = HYDU_send_strlist(proxy->control_fd, proxy->exec_launch_info);
......
......@@ -4,23 +4,17 @@
* See COPYRIGHT in top-level directory.
*/
#ifndef PMI_COMMON_H_INCLUDED
#define PMI_COMMON_H_INCLUDED
#ifndef PM_UTILS_H_INCLUDED
#define PM_UTILS_H_INCLUDED
/* The set of commands supported */
enum HYD_pmcd_pmi_proxy_cmds {
enum HYD_pmu_cmd {
PROC_INFO,
KILL_JOB,
PROXY_SHUTDOWN,
CKPOINT
};
/* FIXME: This structure only provides the PMI_ID, as we currently
* only support single job environments with no dynamic
* processes. When there are multiple jobs or dynamic processes, we
* will need a process group ID as well. */
struct HYD_pmcd_pmi_header {
int pmi_id;
};
HYD_status HYD_pmu_send_exec_info(struct HYD_proxy *proxy);
#endif /* PMI_COMMON_H_INCLUDED */
#endif /* PM_UTILS_H_INCLUDED */
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* (C) 2008 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#include "hydra_base.h"
/* This is here to suppress the "has no symbols" warning on OS X. See
* the MPIU_SUPPRESS_OSX_HAS_NO_SYMBOLS_WARNING macro in mpiutil.h for
* more information. */
static int dummy ATTRIBUTE((unused, used)) = 0;
......@@ -4,11 +4,11 @@
# See COPYRIGHT in top-level directory.
#
AM_CPPFLAGS += -I$(top_srcdir)/ui/utils
bin_PROGRAMS += mpiexec
mpiexec_SOURCES = $(top_srcdir)/ui/mpiexec/callback.c \
$(top_srcdir)/ui/mpiexec/mpiexec.c \
mpiexec_SOURCES = $(top_srcdir)/ui/mpiexec/mpiexec.c \
$(top_srcdir)/ui/mpiexec/utils.c
mpiexec_LDADD = libui.a libpm.a libhydra.a $(external_libs)
mpiexec_CFLAGS = -I$(top_srcdir)/ui/utils
mpiexec_LDFLAGS = $(external_ldflags)
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* (C) 2008 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#include "hydra.h"
#include "hydra_utils.h"
#include "mpiexec.h"
HYD_status HYD_uii_mpx_stdout_cb(void *buf, int buflen)
{
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
status = HYDU_sock_write(STDOUT_FILENO, buf, buflen);
HYDU_ERR_POP(status, "unable to write data to stdout\n");
fn_exit:
HYDU_FUNC_EXIT();
return status;
fn_fail:
goto fn_exit;
}
HYD_status HYD_uii_mpx_stderr_cb(void *buf, int buflen)
{
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
status = HYDU_sock_write(STDERR_FILENO, buf, buflen);
HYDU_ERR_POP(status, "unable to write data to stdout\n");
fn_exit:
HYDU_FUNC_EXIT();
return status;
fn_fail:
goto fn_exit;
}
......@@ -95,7 +95,7 @@ int main(int argc, char **argv)
struct HYD_proxy_exec *exec;
struct HYD_uiu_exec_info *exec_info;
struct HYD_node *node;
int exit_status = 0, i, process_id, proc_count;
int exit_status = 0, i, process_id, proc_count, timeout;
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
......@@ -167,11 +167,21 @@ int main(int argc, char **argv)
HYD_uiu_print_params();
if (getenv("MPIEXEC_TIMEOUT"))
HYD_handle.timeout = atoi(getenv("MPIEXEC_TIMEOUT"));
timeout = atoi(getenv("MPIEXEC_TIMEOUT"));
else
HYD_handle.timeout = -1; /* Set a negative timeout */
timeout = -1; /* Set a negative timeout */
if (HYD_handle.user_global.debug)
HYDU_dump(stdout, "Timeout set to %d (-1 means infinite)\n", HYD_handle.timeout);
HYDU_dump(stdout, "Timeout set to %d (-1 means infinite)\n", timeout);
/* Check if the user wants us to use a port within a certain
* range. */
HYD_handle.port_range = getenv("MPIEXEC_PORTRANGE");
if (!HYD_handle.port_range)
HYD_handle.port_range = getenv("MPIEXEC_PORT_RANGE");
if (!HYD_handle.port_range)
HYD_handle.port_range = getenv("MPICH_PORT_RANGE");
HYD_handle.interface_env_name = HYDU_strdup("MPICH_INTERFACE_NAME");
if (HYD_handle.print_rank_map) {
for (proxy = HYD_handle.pg_list.proxy_list; proxy; proxy = proxy->next) {
......@@ -194,15 +204,15 @@ int main(int argc, char **argv)
}
/* Add the stdout/stdin/stderr callback handlers */
HYD_handle.stdout_cb = HYD_uii_mpx_stdout_cb;
HYD_handle.stderr_cb = HYD_uii_mpx_stderr_cb;
HYD_handle.stdout_cb = HYD_uiu_stdout_cb;
HYD_handle.stderr_cb = HYD_uiu_stderr_cb;
/* Launch the processes */
status = HYD_pmci_launch_procs();
HYDU_ERR_POP(status, "process manager returned error launching processes\n");
/* Wait for their completion */
status = HYD_pmci_wait_for_completion();
status = HYD_pmci_wait_for_completion(timeout);
HYDU_ERR_POP(status, "process manager error waiting for completion\n");
/* Check for the exit status for all the processes */
......
......@@ -10,7 +10,5 @@
#include "hydra.h"
HYD_status HYD_uii_mpx_get_parameters(char **t_argv);
HYD_status HYD_uii_mpx_stdout_cb(void *buf, int buflen);
HYD_status HYD_uii_mpx_stderr_cb(void *buf, int buflen);
#endif /* MPIEXEC_H_INCLUDED */
......@@ -18,6 +18,9 @@ void HYD_uiu_init_params(void)
HYD_handle.rmk = NULL;
HYD_handle.port_range = NULL;
HYD_handle.interface_env_name = NULL;
HYD_handle.ckpoint_int = -1;
HYD_handle.print_rank_map = -1;
......@@ -52,6 +55,12 @@ void HYD_uiu_free_params(void)
if (HYD_handle.rmk)
HYDU_FREE(HYD_handle.rmk);
if (HYD_handle.port_range)
HYDU_FREE(HYD_handle.port_range);
if (HYD_handle.interface_env_name)
HYDU_FREE(HYD_handle.interface_env_name);
if (HYD_handle.user_global.binding)
HYDU_FREE(HYD_handle.user_global.binding);
......@@ -405,3 +414,37 @@ void HYD_uiu_print_params(void)
return;
}
HYD_status HYD_uiu_stdout_cb(void *buf, int buflen)
{
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
status = HYDU_sock_write(STDOUT_FILENO, buf, buflen);
HYDU_ERR_POP(status, "unable to write data to stdout\n");
fn_exit:
HYDU_FUNC_EXIT();
return status;
fn_fail:
goto fn_exit;
}
HYD_status HYD_uiu_stderr_cb(void *buf, int buflen)
{
HYD_status status = HYD_SUCCESS;
HYDU_FUNC_ENTER();
status = HYDU_sock_write(STDERR_FILENO, buf, buflen);
HYDU_ERR_POP(status, "unable to write data to stdout\n");
fn_exit:
HYDU_FUNC_EXIT();
return status;
fn_fail:
goto fn_exit;
}
......@@ -29,5 +29,7 @@ HYD_status HYD_uiu_get_current_exec_info(struct HYD_uiu_exec_info **info);
void HYD_uiu_print_params(void);
HYD_status HYD_uiu_alloc_exec_info(struct HYD_uiu_exec_info **exec_info);
void HYD_uiu_free_exec_info_list(struct HYD_uiu_exec_info *exec_info_list);
HYD_status HYD_uiu_stdout_cb(void *buf, int buflen);
HYD_status HYD_uiu_stderr_cb(void *buf, int buflen);
#endif /* UIU_H_INCLUDED */
......@@ -62,22 +62,21 @@ HYD_status HYDU_sock_listen(int *listen_fd, char *port_range, uint16_t * port)
if (setsockopt(*listen_fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(int)) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set TCP_NODELAY\n");
/* The sockets standard does not guarantee that a successful
* return here means that this is set. However, REUSEADDR not
* being set is not a fatal error, so we ignore that
* case. However, we do check for error cases, which means that
* something bad has happened. */
if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set SO_REUSEADDR\n");
for (i = low_port; i <= high_port; i++) {
memset((void *) &sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(i);
sa.sin_addr.s_addr = INADDR_ANY;
/* The sockets standard does not guarantee that a successful
* return here means that this is set. However, REUSEADDR not
* being set is not a fatal error, so we ignore that
* case. However, we do check for error cases, which means
* that something bad has happened. */
if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
HYDU_ERR_SETANDJUMP(status, HYD_SOCK_ERROR, "cannot set SO_REUSEADDR\n");
if (bind(*listen_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
close(*listen_fd);
/* If the address is in use, we should try the next
* port. Otherwise, it's an error. */
if (errno != EADDRINUSE)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment