/* * Given a buffer containing a network byte order 16-bit integer, * and an arbitrary data string, copy the data string into the location * specified by valp. Also return the sizes of 'valp' in bytes. * Adjust buffer counters. * NOTE: valp is set to point into a newly created buffer, * the caller is responsible for calling xfree() on *valp * if non-NULL (set to NULL on zero size buffer value) */ int unpackmem_xmalloc(char **valp, uint32_t * size_valp, Buf buffer) { uint32_t ns; if (remaining_buf(buffer) < sizeof(ns)) return SLURM_ERROR; memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns)); *size_valp = ntohl(ns); buffer->processed += sizeof(ns); if (*size_valp > MAX_PACK_MEM_LEN) { error("%s: Buffer to be unpacked is too large (%u > %u)", __func__, *size_valp, MAX_PACK_MEM_LEN); return SLURM_ERROR; } else if (*size_valp > 0) { if (remaining_buf(buffer) < *size_valp) return SLURM_ERROR; *valp = xmalloc_nz(*size_valp); memcpy(*valp, &buffer->head[buffer->processed], *size_valp); buffer->processed += *size_valp; } else *valp = NULL; return SLURM_SUCCESS; }
/* * Given 'buffer' pointing to a network byte order 16-bit integer * (size) and a array of strings store the number of strings in * 'size_valp' and the array of strings in valp * NOTE: valp is set to point into a newly created buffer, * the caller is responsible for calling xfree on *valp * if non-NULL (set to NULL on zero size buffer value) */ int unpackstr_array(char ***valp, uint32_t * size_valp, Buf buffer) { int i; uint32_t ns; uint32_t uint32_tmp; if (remaining_buf(buffer) < sizeof(ns)) return SLURM_ERROR; memcpy(&ns, &buffer->head[buffer->processed], sizeof(ns)); *size_valp = ntohl(ns); buffer->processed += sizeof(ns); if (*size_valp > MAX_PACK_ARRAY_LEN) { error("%s: Buffer to be unpacked is too large (%u > %u)", __func__, *size_valp, MAX_PACK_ARRAY_LEN); return SLURM_ERROR; } else if (*size_valp > 0) { *valp = xmalloc_nz(sizeof(char *) * (*size_valp + 1)); for (i = 0; i < *size_valp; i++) { if (unpackmem_xmalloc(&(*valp)[i], &uint32_tmp, buffer)) return SLURM_ERROR; } (*valp)[i] = NULL; /* NULL terminated array so that execle */ /* can detect end of array */ } else *valp = NULL; return SLURM_SUCCESS; }
extern ssize_t slurm_msg_recvfrom_timeout(int fd, char **pbuf, size_t *lenp, uint32_t flags, int tmout) { ssize_t len; uint32_t msglen; len = slurm_recv_timeout( fd, (char *)&msglen, sizeof(msglen), 0, tmout ); if (len < ((ssize_t) sizeof(msglen))) return SLURM_ERROR; msglen = ntohl(msglen); if (msglen > MAX_MSG_SIZE) slurm_seterrno_ret(SLURM_PROTOCOL_INSANE_MSG_LENGTH); /* * Allocate memory on heap for message */ *pbuf = xmalloc_nz(msglen); if (slurm_recv_timeout(fd, *pbuf, msglen, 0, tmout) != msglen) { xfree(*pbuf); *pbuf = NULL; return SLURM_ERROR; } *lenp = msglen; return (ssize_t) msglen; }
/* Process incoming RPCs. Meant to execute as a pthread */ extern void *rpc_mgr(void *no_data) { int sockfd, newsockfd; int i; uint16_t port; slurm_addr_t cli_addr; slurmdbd_conn_t *conn_arg = NULL; master_thread_id = pthread_self(); /* initialize port for RPCs */ if ((sockfd = slurm_init_msg_engine_port(get_dbd_port())) == SLURM_SOCKET_ERROR) fatal("slurm_init_msg_engine_port error %m"); slurm_persist_conn_recv_server_init(); /* * Process incoming RPCs until told to shutdown */ while (!shutdown_time && (i = slurm_persist_conn_wait_for_thread_loc()) >= 0) { /* * accept needed for stream implementation is a no-op in * message implementation that just passes sockfd to newsockfd */ if ((newsockfd = slurm_accept_msg_conn(sockfd, &cli_addr)) == SLURM_SOCKET_ERROR) { slurm_persist_conn_free_thread_loc(i); if (errno != EINTR) error("slurm_accept_msg_conn: %m"); continue; } fd_set_nonblocking(newsockfd); conn_arg = xmalloc(sizeof(slurmdbd_conn_t)); conn_arg->conn = xmalloc(sizeof(slurm_persist_conn_t)); conn_arg->conn->fd = newsockfd; conn_arg->conn->flags = PERSIST_FLAG_DBD; conn_arg->conn->callback_proc = proc_req; conn_arg->conn->callback_fini = _connection_fini_callback; conn_arg->conn->shutdown = &shutdown_time; conn_arg->conn->version = SLURM_MIN_PROTOCOL_VERSION; conn_arg->conn->rem_host = xmalloc_nz(sizeof(char) * 16); /* Don't fill in the rem_port here. It will be filled in * later if it is a slurmctld connection. */ slurm_get_ip_str(&cli_addr, &port, conn_arg->conn->rem_host, sizeof(char) * 16); slurm_persist_conn_recv_thread_init( conn_arg->conn, i, conn_arg); } debug("rpc_mgr shutting down"); (void) slurm_shutdown_msg_engine(sockfd); pthread_exit((void *) 0); return NULL; }
/* init_buf - create an empty buffer of the given size */ Buf init_buf(int size) { Buf my_buf; if (size > MAX_BUF_SIZE) { error("%s: Buffer size limit exceeded (%u > %u)", __func__, size, MAX_BUF_SIZE); return NULL; } if (size <= 0) size = BUF_SIZE; my_buf = xmalloc_nz(sizeof(struct slurm_buf)); my_buf->magic = BUF_MAGIC; my_buf->size = size; my_buf->processed = 0; my_buf->head = xmalloc_nz(sizeof(char)*size); return my_buf; }
int unpacklongdouble_array(long double **valp, uint32_t* size_val, Buf buffer) { uint32_t i = 0; if (unpack32(size_val, buffer)) return SLURM_ERROR; *valp = xmalloc_nz((*size_val) * sizeof(long double)); for (i = 0; i < *size_val; i++) { if (unpacklongdouble((*valp) + i, buffer)) return SLURM_ERROR; } return SLURM_SUCCESS; }
/* create_buf - create a buffer with the supplied contents, contents must * be xalloc'ed */ Buf create_buf(char *data, int size) { Buf my_buf; if (size > MAX_BUF_SIZE) { error("%s: Buffer size limit exceeded (%u > %u)", __func__, size, MAX_BUF_SIZE); return NULL; } my_buf = xmalloc_nz(sizeof(struct slurm_buf)); my_buf->magic = BUF_MAGIC; my_buf->size = size; my_buf->processed = 0; my_buf->head = data; return my_buf; }
extern void msg_aggr_add_comp(Buf buffer, void *auth_cred, header_t *header) { slurm_msg_t *msg; if (!msg_collection.running) return; msg = xmalloc_nz(sizeof(slurm_msg_t)); slurm_msg_t_init(msg); msg->protocol_version = header->version; msg->msg_type = header->msg_type; msg->flags = header->flags; msg->auth_cred = auth_cred; msg->data = buffer; msg->data_size = remaining_buf(buffer); msg_aggr_add_msg(msg, 0, NULL); }
/* Determine if core dump in progress * stat_fname - Pathname of the form /proc/<PID>/stat * RET - True if core dump in progress, otherwise false */ static bool _test_core_dumping(char* stat_fname) { int pid, ppid, pgrp, session, tty, tpgid; char cmd[16], state[1]; long unsigned flags, min_flt, cmin_flt, maj_flt, cmaj_flt; long unsigned utime, stime; long cutime, cstime, priority, nice, timeout, it_real_value; long resident_set_size; long unsigned start_time, vsize; long unsigned resident_set_size_rlim, start_code, end_code; long unsigned start_stack, kstk_esp, kstk_eip; long unsigned w_chan, n_swap, sn_swap; int l_proc; int num; char *str_ptr, *proc_stat; int proc_fd, proc_stat_size = BUF_SIZE; bool dumping_results = false; proc_fd = open(stat_fname, O_RDONLY, 0); if (proc_fd == -1) return false; /* process is now gone */ proc_stat = xmalloc_nz(proc_stat_size + 1); while (1) { num = read(proc_fd, proc_stat, proc_stat_size); if (num <= 0) { proc_stat[0] = '\0'; break; } proc_stat[num] = '\0'; if (num < proc_stat_size) break; proc_stat_size += BUF_SIZE; xrealloc_nz(proc_stat, proc_stat_size + 1); if (lseek(proc_fd, (off_t) 0, SEEK_SET) != 0) break; } close(proc_fd); /* race condition at process termination */ if (proc_stat[0] == '\0') { debug("%s: %s is empty", __func__, stat_fname); xfree(proc_stat); return false; } /* split into "PID (cmd" and "<rest>" */ str_ptr = (char *)strrchr(proc_stat, ')'); if (str_ptr == NULL) { error("%s: unexpected format of %s (%s) bracket missing?", __func__, stat_fname, proc_stat); xfree(proc_stat); return false; } *str_ptr = '\0'; /* replace trailing ')' with NULL */ /* parse these two strings separately, skipping the leading "(". */ memset (cmd, 0, sizeof(cmd)); sscanf (proc_stat, "%d (%15c", &pid, cmd); /* comm[16] in kernel */ num = sscanf(str_ptr + 2, /* skip space after ')' too */ "%c " "%d %d %d %d %d " "%lu %lu %lu %lu %lu %lu %lu " "%ld %ld %ld %ld %ld %ld " "%lu %lu " "%ld " "%lu %lu %lu " "%lu %lu %lu " "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ "%lu %lu %lu %*d %d", state, &ppid, &pgrp, &session, &tty, &tpgid, &flags, &min_flt, &cmin_flt, &maj_flt, &cmaj_flt, &utime, &stime, &cutime, &cstime, &priority, &nice, &timeout, &it_real_value, &start_time, &vsize, &resident_set_size, &resident_set_size_rlim, &start_code, &end_code, &start_stack, &kstk_esp, &kstk_eip, /* &signal, &blocked, &sig_ignore, &sig_catch, */ /* can't use */ &w_chan, &n_swap, &sn_swap /* , &Exit_signal */, &l_proc); if (num < 13) error("/proc entry too short (%s)", proc_stat); else if (flags & PF_DUMPCORE) dumping_results = true; xfree(proc_stat); return dumping_results; }