Esempio n. 1
0
int entermsg(struct DayDream_Message *msg, int reply, char *params)
{
    char ebuf[1024];
    int hola;
    int msgfd;
    char *s;
    struct DayDream_Message header;
    char *lineedmem;

    int recoff;

    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'E' && ((access1 & (1L << SECB_FIDOMESSAGE)) == 0)) {
        DDPut(sd[emnofidomsgstr]);
        return 0;
    }
    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'N' && ((access2 & (1L << SECB_SENDNETMAIL)) == 0)) {
        DDPut(sd[emnonetmsgstr]);
        return 0;
    }
    changenodestatus("Entering a message");
    if (msg) {
        memcpy(&header, msg, sizeof(struct DayDream_Message));
    } else {
        s = (char *) &header;
        memset(&header, 0, sizeof(struct DayDream_Message));
        if (params)
            strncpy(header.MSG_RECEIVER, params, 25);
    }

    if (current_msgbase->MSGBASE_FLAGS & (1L << 0) && current_msgbase->MSGBASE_FLAGS & (1L << 1)) {
        DDPut(sd[emnomsgsstr]);
        return 0;
    }
    DDPut(sd[emhead1str]);
    DDPut(current_msgbase->MSGBASE_NAME);
    ebuf[0] = 0;
    strlcat(ebuf, sd[emhead2str], sizeof ebuf);
    hola = 61 - strlen(current_msgbase->MSGBASE_NAME);
    while (hola) {
        strlcat(ebuf, "-", sizeof ebuf);
        hola--;
    }
    DDPut(ebuf);
    ddprintf(sd[emhead3str], highest);
    DDPut(sd[emhead4str]);

    if ((current_msgbase->MSGBASE_FLAGS & (1L << 0)) || (header.MSG_FLAGS & (1L << 0))) {
        DDPut(sd[emprvstr]);
        header.MSG_FLAGS |= (1L << 0);
    } else {
        DDPut(sd[empubstr]);
    }
    header.MSG_CREATION = time(0);
    DDPut(sd[emhead5str]);
    DDPut(ctime(&header.MSG_CREATION));

    DDPut(sd[emhead6str]);
    if (current_msgbase->MSGBASE_FLAGS & (1L << 2)) {
        strlcpy(header.MSG_AUTHOR, user.user_handle, sizeof header.MSG_AUTHOR);
    } else {
        strlcpy(header.MSG_AUTHOR, user.user_realname, sizeof header.MSG_AUTHOR);
    }
    DDPut(header.MSG_AUTHOR);
    for (;;) {
askrec:
        DDPut(sd[emhead7str]);
        if (!(Prompt(header.MSG_RECEIVER, 25, 0)))
            return 0;
        if (header.MSG_RECEIVER[0] == 0 || (!strcasecmp(header.MSG_RECEIVER, "all")) || (!strcasecmp(header.MSG_RECEIVER, "all users"))) {
            if (current_msgbase->MSGBASE_FLAGS & (1L << 0)) {
                DDPut(sd[emhead8str]);
                HotKey(0);
                header.MSG_RECEIVER[0] = 0;
            } else {
                DDPut(sd[emhead9str]);
                header.MSG_RECEIVER[0] = 0;
                break;
            }
        } else if (!strcasecmp(header.MSG_RECEIVER, "eall")) {
            if (current_msgbase->MSGBASE_FLAGS & (1L << 0)) {
                DDPut(sd[emhead8str]);
                HotKey(0);
                header.MSG_RECEIVER[0] = 0;
            } else if (access1 & (1L << SECB_EALLMESSAGE)) {
                header.MSG_RECEIVER[0] = -1;
                DDPut(sd[emhead10str]);
                break;
            } else {
                DDPut(sd[emnopoststr]);
                HotKey(0);
                header.MSG_RECEIVER[0] = 0;
            }
        } else {
            if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'L') {
                struct userbase user;

                if (!strcasecmp(header.MSG_RECEIVER, "sysop")) {
                    recoff = 0;
                } else {
                    recoff = findusername(header.MSG_RECEIVER);
                }
                if (recoff == -1 ||
                        getubentbyid(recoff, &user) == -1) {
                    DDPut(sd[emnouserstr]);
                    HotKey(0);
                    goto askrec;
                }

                if (!checkconfaccess(conference()->conf.CONF_NUMBER, &user)) {
                    DDPut(sd[emnoaccessstr]);
                    HotKey(0);
                }
                DDPut("                     ");
                if (current_msgbase->MSGBASE_FLAGS & (1L << 2)) {
                    strlcpy(header.MSG_RECEIVER,
                            user.user_handle,
                            sizeof header.MSG_RECEIVER);
                } else {
                    strlcpy(header.MSG_RECEIVER,
                            user.user_realname,
                            sizeof header.MSG_RECEIVER);
                }
                DDPut(header.MSG_RECEIVER);
                break;
            } else
                break;
        }
    }
    DDPut(sd[emsubjectstr]);
    if (!(Prompt(header.MSG_SUBJECT, 67, 0)))
        return 0;
    if (header.MSG_SUBJECT[0] == 0) {
        DDPut(sd[emabortedstr]);
        return 0;
    }
    DDPut("                                                                       ");
    if (header.MSG_RECEIVER[0] == 0 || header.MSG_RECEIVER[0] == -1 || header.MSG_FLAGS & (1L << 0) || current_msgbase->MSGBASE_FLAGS & (1L << 1)) {

    } else {
        DDPut(sd[emisprivatestr]);
        hola = HotKey(HOT_NOYES);
        if (hola == 0)
            return 0;
        if (hola == 1)
            header.MSG_FLAGS |= MSG_FLAGS_PRIVATE;
    }

    if ((header.MSG_FLAGS & (1L << 0)) == 0 && (access1 & (1L << SECB_PUBLICMESSAGE)) == 0) {
        DDPut(sd[emnopubstr]);
        return 0;
    }
    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'N') {
        if (header.MSG_FN_DEST_NET) {
            snprintf(ebuf, sizeof ebuf, "%d:%d/%d.%d",
                     header.MSG_FN_DEST_ZONE,
                     header.MSG_FN_DEST_NET,
                     header.MSG_FN_DEST_NODE,
                     header.MSG_FN_DEST_POINT);
        } else {
            *ebuf = 0;
        }
        DDPut(sd[emnetaddstr]);
        if (!(Prompt(ebuf, 30, 0)))
            return 0;
        if (!str2addr(ebuf, &header.MSG_FN_DEST_ZONE, &header.MSG_FN_DEST_NET,
                      &header.MSG_FN_DEST_NODE, &header.MSG_FN_DEST_POINT))
            return 0;
        if(access2 & (1L << SECB_CRASH)) {
            DDPut(sd[emnetcrashstr]);
            if(HotKey(HOT_NOYES) == 1) {
                header.MSG_FLAGS |= MSG_FLAGS_CRASH;
            }
        }
        DDPut(sd[emnetkillstr]);
        if(HotKey(HOT_YESNO) == 1) {
            header.MSG_FLAGS |= MSG_FLAGS_KILL_SENT;
        }
    }
    *header.MSG_ATTACH = 0;

    if (current_msgbase->MSGBASE_FLAGS & (1L << 5)) {
        if ((header.MSG_FLAGS & (1L << 0)) && (access2 & (1L << SECB_PVTATTACH))) {
            *header.MSG_ATTACH = 1;
        } else if (((header.MSG_FLAGS & (1L << 0)) == 0) && (access2 & (1L << SECB_PUBATTACH))) {
            *header.MSG_ATTACH = 1;
        }
    }
    if (reply) {
        if (!askqlines()) {
            snprintf(ebuf, sizeof ebuf, "%s/daydream%d.msg",
                     DDTMP, node);
            unlink(ebuf);
        }
        DDPut("\n\n");
    }
    /* XXX: size should be replaced by a constant! */
    lineedmem = (char *) xmalloc(80 * 500);
    hola = edfile(lineedmem, 80 * 500, reply, &header);
    if (hola == 0) {
        char fabuf[1024];

        DDPut(sd[emaborted2str]);
        free(lineedmem);
        if (cleantemp() == -1) {
            DDPut(sd[tempcleanerrstr]);
            return 0;
        }
        snprintf(fabuf, sizeof fabuf, "%s/attachs.%d", DDTMP, node);
        unlink(fabuf);

        return 0;
    }
    DDPut(sd[emsavingstr]);

    getmsgptrs();
    highest++;
    header.MSG_NUMBER = highest;
    if (setmsgptrs() == 0) {
        free(lineedmem);
        return 0;
    }
    if (*header.MSG_ATTACH) {
        char fabuf[1024];
        FILE *fd;

        snprintf(fabuf, sizeof fabuf, "%s/attachs.%d", DDTMP, node);
        if ((fd = fopen(fabuf, "r"))) {
            char hoobab[1024];

            snprintf(hoobab, sizeof hoobab, "%s/messages/base%3.3d/fa%5.5d", conference()->conf.CONF_PATH, current_msgbase->MSGBASE_NUMBER, header.MSG_NUMBER);
            mkdir(hoobab, 0777);
            setperm(hoobab, 0777);

            while (fgetsnolf(hoobab, 1024, fd)) {
                char sr[1024];
                char de[1024];
                snprintf(sr, sizeof sr, "%s/%s", currnode->MULTI_TEMPORARY, hoobab);
                snprintf(de, sizeof de, "%s/messages/base%3.3d/fa%5.5d/%s", conference()->conf.CONF_PATH, current_msgbase->MSGBASE_NUMBER, header.MSG_NUMBER, hoobab);
                newrename(sr, de);
            }
            fclose(fd);
            snprintf(hoobab, sizeof hoobab, "%s/messages/base%3.3d/msf%5.5d", conference()->conf.CONF_PATH, current_msgbase->MSGBASE_NUMBER, header.MSG_NUMBER);
            newrename(fabuf, hoobab);
        } else {
            *header.MSG_ATTACH = 0;
        }
    }

    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) != 'L') {
        header.MSG_FN_ORIG_ZONE = current_msgbase->MSGBASE_FN_ZONE;
        header.MSG_FN_ORIG_NET = current_msgbase->MSGBASE_FN_NET;
        header.MSG_FN_ORIG_NODE = current_msgbase->MSGBASE_FN_NODE;
        header.MSG_FN_ORIG_POINT = current_msgbase->MSGBASE_FN_POINT;
        header.MSG_FLAGS |= (1L << 2);
    }
    if ((msgfd = ddmsg_open_base(conference()->conf.CONF_PATH, current_msgbase->MSGBASE_NUMBER, O_RDWR | O_CREAT, 0666)) == -1) {
        DDPut(sd[emwriteerrstr]);
        free(lineedmem);
        return 0;
    }
    fsetperm(msgfd, 0666);
    lseek(msgfd, 0, SEEK_END);
    safe_write(msgfd, &header, sizeof(struct DayDream_Message));
    ddmsg_close_base(msgfd);

    if ((msgfd = ddmsg_open_msg(conference()->conf.CONF_PATH, current_msgbase->MSGBASE_NUMBER, header.MSG_NUMBER, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
        DDPut(sd[emwriteerrstr]);
        free(lineedmem);
        return 0;
    }
    fsetperm(msgfd, 0666);
    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'E') {
        char ub[128];
        int uq;

        strlcpy(ub, current_msgbase->MSGBASE_FN_TAG, sizeof ub);
        strupr(ub);
        snprintf(ebuf, sizeof ebuf, "AREA:%s\n", ub);
        safe_write(msgfd, ebuf, strlen(ebuf));
        if ((uq = getfidounique())) {
            snprintf(ebuf, sizeof ebuf, "\001MSGID: %d:%d/%d.%d %8.8x\n", current_msgbase->MSGBASE_FN_ZONE, current_msgbase->MSGBASE_FN_NET, current_msgbase->MSGBASE_FN_NODE, current_msgbase->MSGBASE_FN_POINT, uq);
            safe_write(msgfd, ebuf, strlen(ebuf));
            if (header.MSG_ORIGINAL) {
                if (getreplyid(header.MSG_ORIGINAL, ebuf, sizeof ebuf))
                    safe_write(msgfd, ebuf, strlen(ebuf));
            }
        }
    } else if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'N') {
        snprintf(ebuf, sizeof ebuf, "\001INTL %d:%d/%d %d:%d/%d\n",
                 header.MSG_FN_DEST_ZONE, header.MSG_FN_DEST_NET,
                 header.MSG_FN_DEST_NODE, header.MSG_FN_ORIG_ZONE,
                 header.MSG_FN_ORIG_NET, header.MSG_FN_ORIG_NODE);
        safe_write(msgfd, ebuf, strlen(ebuf));

        if (header.MSG_FN_DEST_POINT) {
            snprintf(ebuf, sizeof ebuf, "\001TOPT %d\n", header.MSG_FN_DEST_POINT);
            safe_write(msgfd, ebuf, strlen(ebuf));
        }
        if (header.MSG_FN_ORIG_POINT) {
            snprintf(ebuf, sizeof ebuf, "\001FMPT %d\n", header.MSG_FN_ORIG_POINT);
            safe_write(msgfd, ebuf, strlen(ebuf));
        }
    }
    s = lineedmem;
    while (hola) {
        snprintf(ebuf, sizeof ebuf, "%s\n", s);
        safe_write(msgfd, ebuf, strlen(ebuf));
        hola--;
        s = &s[80];
    }

//	place holder, user auto-sig goes here
//	snprintf(ebuf, sizeof ebuf, "signature here");
//	safe_write(msgfd, ebuf, strlen(ebuf));

    if (toupper(current_msgbase->MSGBASE_FN_FLAGS) == 'E') {
        snprintf(ebuf, sizeof ebuf, "\n--- DayDream BBS/UNIX (" UNAME ") %s\n * Origin: %s (%d:%d/%d)\nSEEN-BY: %d/%d\n", versionstring, current_msgbase->MSGBASE_FN_ORIGIN, current_msgbase->MSGBASE_FN_ZONE, current_msgbase->MSGBASE_FN_NET, current_msgbase->MSGBASE_FN_NODE, current_msgbase->MSGBASE_FN_NET, current_msgbase->MSGBASE_FN_NODE);
        safe_write(msgfd, ebuf, strlen(ebuf));
    } else if (toupper(current_msgbase->MSGBASE_FN_FLAGS) != 'L') {
        snprintf(ebuf, sizeof ebuf, "\n--- DayDream BBS/UNIX (" UNAME ") %s\n", versionstring);
        safe_write(msgfd, ebuf, strlen(ebuf));
    }
    ddmsg_close_msg(msgfd);

    DDPut(sd[emdonestr]);
    free(lineedmem);

    if (header.MSG_FLAGS & (1L << 0)) {
        user.user_pvtmessages++;
        clog.cl_pvtmessages++;
    } else {
        user.user_pubmessages++;
        clog.cl_pubmessages++;
    }
    return 1;
}
Esempio n. 2
0
static int
_handle_signal_task_local(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int signal;
	int ltaskid; /* local task index */

	safe_read(fd, &signal, sizeof(int));
	safe_read(fd, &ltaskid, sizeof(int));
	debug("_handle_signal_task_local for step=%u.%u uid=%d signal=%d",
	      job->jobid, job->stepid, (int) uid, signal);

	if (uid != job->uid && !_slurm_authorized_user(uid)) {
		debug("kill req from uid %ld for job %u.%u owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = EPERM;
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (ltaskid < 0 || ltaskid >= job->node_tasks) {
		debug("step %u.%u invalid local task id %d",
		      job->jobid, job->stepid, ltaskid);
		rc = SLURM_ERROR;
		goto done;
	}
	if (!job->task
	    || !job->task[ltaskid]) {
		debug("step %u.%u no task info for task id %d",
		      job->jobid, job->stepid, ltaskid);
		rc = SLURM_ERROR;
		goto done;
	}
	if (job->task[ltaskid]->pid <= 1) {
		debug("step %u.%u invalid pid %d for task %d",
		      job->jobid, job->stepid,
		      job->task[ltaskid]->pid, ltaskid);
		rc = SLURM_ERROR;
		goto done;
	}

	/*
	 * Signal the task
	 */
	slurm_mutex_lock(&suspend_mutex);
	if (suspended) {
		rc = ESLURMD_STEP_SUSPENDED;
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	}

	if (kill(job->task[ltaskid]->pid, signal) == -1) {
		rc = -1;
		verbose("Error sending signal %d to %u.%u, pid %d: %m",
			signal, job->jobid, job->stepid,
			job->task[ltaskid]->pid);
	} else {
		verbose("Sent signal %d to %u.%u, pid %d",
			signal, job->jobid, job->stepid,
			job->task[ltaskid]->pid);
	}
	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code */
	safe_write(fd, &rc, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 3
0
static int
_handle_checkpoint_tasks(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	time_t timestamp;
	int len;
	char *image_dir = NULL;

	debug3("_handle_checkpoint_tasks for job %u.%u",
	       job->jobid, job->stepid);

	safe_read(fd, &timestamp, sizeof(time_t));
	safe_read(fd, &len, sizeof(int));
	if (len) {
		image_dir = xmalloc (len);
		safe_read(fd, image_dir, len); /* '\0' terminated */
	}

	debug3("  uid = %d", uid);
	if (uid != job->uid && !_slurm_authorized_user(uid)) {
		debug("checkpoint req from uid %ld for job %u.%u "
		      "owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = EPERM;
		goto done;
	}

	if (job->ckpt_timestamp &&
	    timestamp == job->ckpt_timestamp) {
		debug("duplicate checkpoint req for job %u.%u, "
		      "timestamp %ld. discarded.",
		      job->jobid, job->stepid, (long)timestamp);
		rc = ESLURM_ALREADY_DONE; /* EINPROGRESS? */
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (job->pgid <= (pid_t)1) {
		debug ("step %u.%u invalid [jmgr_pid:%d pgid:%u]",
		       job->jobid, job->stepid, job->jmgr_pid, job->pgid);
		rc = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	slurm_mutex_lock(&suspend_mutex);
	if (suspended) {
		rc = ESLURMD_STEP_SUSPENDED;
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	}

	/* set timestamp in case another request comes */
	job->ckpt_timestamp = timestamp;

	/* TODO: do we need job->ckpt_dir any more,
	 *	except for checkpoint/xlch? */
/*	if (! image_dir) { */
/*		image_dir = xstrdup(job->ckpt_dir); */
/*	} */

	/* call the plugin to send the request */
	if (checkpoint_signal_tasks(job, image_dir) != SLURM_SUCCESS) {
		rc = -1;
		verbose("Error sending checkpoint request to %u.%u: %s",
			job->jobid, job->stepid, slurm_strerror(rc));
	} else {
		verbose("Sent checkpoint request to %u.%u",
			job->jobid, job->stepid);
	}

	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code */
	safe_write(fd, &rc, sizeof(int));
	xfree(image_dir);
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 4
0
static int
_handle_suspend(int fd, stepd_step_rec_t *job, uid_t uid)
{
	static int launch_poe = -1;
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	uint16_t job_core_spec = (uint16_t) NO_VAL;

	safe_read(fd, &job_core_spec, sizeof(uint16_t));

	debug("_handle_suspend for step:%u.%u uid:%ld core_spec:%u",
	      job->jobid, job->stepid, (long)uid, job_core_spec);

	if (!_slurm_authorized_user(uid)) {
		debug("job step suspend request from uid %ld for job %u.%u ",
		      (long)uid, job->jobid, job->stepid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	_wait_for_job_init(job);

	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	acct_gather_suspend_poll();
	if (launch_poe == -1) {
		char *launch_type = slurm_get_launch_type();
		if (!xstrcmp(launch_type, "launch/poe"))
			launch_poe = 1;
		else
			launch_poe = 0;
		xfree(launch_type);
	}

	/*
	 * Signal the container
	 */
	slurm_mutex_lock(&suspend_mutex);
	if (suspended) {
		rc = -1;
		errnum = ESLURMD_STEP_SUSPENDED;
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	} else {
		if (!job->batch && switch_g_job_step_pre_suspend(job))
			error("switch_g_job_step_pre_suspend: %m");

		/* SIGTSTP is sent first to let MPI daemons stop their tasks,
		 * then wait 2 seconds, then send SIGSTOP to the spawned
		 * process's container to stop everything else.
		 *
		 * In some cases, 1 second has proven insufficient. Longer
		 * delays may help insure that all MPI tasks have been stopped
		 * (that depends upon the MPI implementaiton used), but will
		 * also permit longer time periods when more than one job can
		 * be running on each resource (not good). */
		if (launch_poe == 0) {
			/* IBM MPI seens to periodically hang upon receipt
			 * of SIGTSTP. */
			if (proctrack_g_signal(job->cont_id, SIGTSTP) < 0) {
				verbose("Error suspending %u.%u (SIGTSTP): %m",
					job->jobid, job->stepid);
			} else
				sleep(2);
		}

		if (proctrack_g_signal(job->cont_id, SIGSTOP) < 0) {
			verbose("Error suspending %u.%u (SIGSTOP): %m",
				job->jobid, job->stepid);
		} else {
			verbose("Suspended %u.%u", job->jobid, job->stepid);
		}
		suspended = true;
	}
	if (!job->batch && switch_g_job_step_post_suspend(job))
		error("switch_g_job_step_post_suspend: %m");
	if (!job->batch && core_spec_g_suspend(job->cont_id, job_core_spec))
		error("core_spec_g_suspend: %m");

	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errno */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 5
0
static int
_handle_completion(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	int first;
	int last;
	jobacctinfo_t *jobacct = NULL;
	int step_rc;
	char* buf;
	int len;
	Buf buffer;
	bool lock_set = false;

	debug("_handle_completion for job %u.%u",
	      job->jobid, job->stepid);

	debug3("  uid = %d", uid);
	if (!_slurm_authorized_user(uid)) {
		debug("step completion message from uid %ld for job %u.%u ",
		      (long)uid, job->jobid, job->stepid);
		rc = -1;
		errnum = EPERM;
		/* Send the return code and errno */
		safe_write(fd, &rc, sizeof(int));
		safe_write(fd, &errnum, sizeof(int));
		return SLURM_SUCCESS;
	}

	safe_read(fd, &first, sizeof(int));
	safe_read(fd, &last, sizeof(int));
	safe_read(fd, &step_rc, sizeof(int));

	/*
	 * We must not use getinfo over a pipe with slurmd here
	 * Indeed, slurmstepd does a large use of setinfo over a pipe
	 * with slurmd and doing the reverse can result in a deadlock
	 * scenario with slurmd :
	 * slurmd(lockforread,write)/slurmstepd(write,lockforread)
	 * Do pack/unpack instead to be sure of independances of
	 * slurmd and slurmstepd
	 */
	safe_read(fd, &len, sizeof(int));
	buf = xmalloc(len);
	safe_read(fd, buf, len);
	buffer = create_buf(buf, len);
	jobacctinfo_unpack(&jobacct, SLURM_PROTOCOL_VERSION,
			   PROTOCOL_TYPE_SLURM, buffer, 1);
	free_buf(buffer);

	/*
	 * Record the completed nodes
	 */
	slurm_mutex_lock(&step_complete.lock);
	lock_set = true;
	if (! step_complete.wait_children) {
		rc = -1;
		errnum = ETIMEDOUT; /* not used anyway */
		goto timeout;
	}

	/* SlurmUser or root can craft a launch without a valid credential
	 * ("srun --no-alloc ...") and no tree information can be built
	 *  without the hostlist from the credential. */
	if (step_complete.rank >= 0) {
#if 0
		char bits_string[128];
		debug2("Setting range %d (bit %d) through %d(bit %d)",
		       first, first-(step_complete.rank+1),
		       last, last-(step_complete.rank+1));
		bit_fmt(bits_string, sizeof(bits_string), step_complete.bits);
		debug2("  before bits: %s", bits_string);
#endif
		bit_nset(step_complete.bits,
			 first - (step_complete.rank+1),
			 last - (step_complete.rank+1));
#if 0
		bit_fmt(bits_string, sizeof(bits_string), step_complete.bits);
		debug2("  after bits: %s", bits_string);
#endif
	}
	step_complete.step_rc = MAX(step_complete.step_rc, step_rc);

	/************* acct stuff ********************/
	jobacctinfo_aggregate(step_complete.jobacct, jobacct);
timeout:
	jobacctinfo_destroy(jobacct);
	/*********************************************/

	/* Send the return code and errno, we do this within the locked
	 * region to ensure that the stepd doesn't exit before we can
	 * perform this send. */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	slurm_cond_signal(&step_complete.cond);
	slurm_mutex_unlock(&step_complete.lock);

	return SLURM_SUCCESS;


rwfail:	if (lock_set) {
		slurm_cond_signal(&step_complete.cond);
		slurm_mutex_unlock(&step_complete.lock);
	}
	return SLURM_FAILURE;
}
Esempio n. 6
0
File: req.c Progetto: lipari/slurm
static int
_handle_signal_container(int fd, slurmd_job_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	int sig;
	static int msg_sent = 0;

	debug("_handle_signal_container for job %u.%u",
	      job->jobid, job->stepid);

	safe_read(fd, &sig, sizeof(int));

	debug3("  uid = %d", uid);
	if (uid != job->uid && !_slurm_authorized_user(uid)) {
		debug("kill container req from uid %ld for job %u.%u "
		      "owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	if ((job->nodeid == 0) && (msg_sent == 0) &&
	    (job->state < SLURMSTEPD_STEP_ENDING)) {
		time_t now = time(NULL);
		char entity[24], time_str[24];
		if (job->stepid == SLURM_BATCH_SCRIPT) {
			snprintf(entity, sizeof(entity), "JOB %u", job->jobid);
		} else {
			snprintf(entity, sizeof(entity), "STEP %u.%u",
				 job->jobid, job->stepid);
		}
		slurm_make_time_str(&now, time_str, sizeof(time_str));

		/* Not really errors,
		 * but we want messages displayed by default */
		if (sig == SIG_TIME_LIMIT) {
			error("*** %s CANCELLED AT %s DUE TO TIME LIMIT ***",
			      entity, time_str);
			msg_sent = 1;
		} else if (sig == SIG_PREEMPTED) {
			error("*** %s CANCELLED AT %s DUE TO PREEMPTION ***",
			      entity, time_str);
			msg_sent = 1;
		} else if (sig == SIG_NODE_FAIL) {
			error("*** %s CANCELLED AT %s DUE TO NODE FAILURE ***",
			      entity, time_str);
			msg_sent = 1;
		} else if (sig == SIG_FAILURE) {
			error("*** %s FAILED (non-zero exit code or other "
			      "failure mode) ***", entity);
			msg_sent = 1;
		} else if ((sig == SIGTERM) || (sig == SIGKILL)) {
			error("*** %s CANCELLED AT %s ***", entity, time_str);
			msg_sent = 1;
		}
	}
	if ((sig == SIG_TIME_LIMIT) || (sig == SIG_NODE_FAIL) ||
	    (sig == SIG_PREEMPTED)  || (sig == SIG_FAILURE))
		goto done;
	if (sig == SIG_DEBUG_WAKE) {
		int i;
		for (i = 0; i < job->node_tasks; i++)
			pdebug_wake_process(job, job->task[i]->pid);
		goto done;
	}
	if (sig == SIG_ABORT) {
		sig = SIGKILL;
		job->aborted = true;
	}

	pthread_mutex_lock(&suspend_mutex);
	if (suspended && (sig != SIGKILL)) {
		rc = -1;
		errnum = ESLURMD_STEP_SUSPENDED;
		pthread_mutex_unlock(&suspend_mutex);
		goto done;
	}

	/*
	 * Signal the container
	 */
	if (slurm_container_signal(job->cont_id, sig) < 0) {
		rc = -1;
		errnum = errno;
		verbose("Error sending signal %d to %u.%u: %m",
			sig, job->jobid, job->stepid);
	} else {
		verbose("Sent signal %d to %u.%u",
			sig, job->jobid, job->stepid);
	}
	pthread_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errnum */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 7
0
static int
_handle_terminate(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	stepd_step_task_info_t *task;
	uint32_t i;

	debug("_handle_terminate for step=%u.%u uid=%d",
	      job->jobid, job->stepid, uid);
	step_terminate_monitor_start(job->jobid, job->stepid);

	if (uid != job->uid && !_slurm_authorized_user(uid)) {
		debug("terminate req from uid %ld for job %u.%u "
		      "owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	/* cycle thru the tasks and mark those that have not
	 * called abort and/or terminated as killed_by_cmd
	 */
	for (i = 0; i < job->node_tasks; i++) {
		if (NULL == (task = job->task[i])) {
			continue;
		}
		if (task->aborted || task->exited) {
			continue;
		}
		/* mark that this task is going to be killed by
		 * cmd so we ignore its exit status - otherwise,
		 * we will probably report the final exit status
		 * as SIGKILL
		 */
		task->killed_by_cmd = true;
	}

	/*
	 * Signal the container with SIGKILL
	 */
	slurm_mutex_lock(&suspend_mutex);
	if (suspended) {
		debug("Terminating suspended job step %u.%u",
		      job->jobid, job->stepid);
		suspended = false;
	}

	if (proctrack_g_signal(job->cont_id, SIGKILL) < 0) {
		if (errno != ESRCH) {	/* No error if process already gone */
			rc = -1;
			errnum = errno;
		}
		verbose("Error sending SIGKILL signal to %u.%u: %m",
			job->jobid, job->stepid);
	} else {
		verbose("Sent SIGKILL signal to %u.%u",
			job->jobid, job->stepid);
	}
	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errnum */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 8
0
static int
decompress_fd_xz(int fdi, int fdo)
{
#ifdef HAVE_LZMA
    uint8_t buf_in[BUFSIZ];
    uint8_t buf_out[BUFSIZ];

    lzma_stream strm = LZMA_STREAM_INIT;
    lzma_ret ret = lzma_stream_decoder(&strm, UINT64_MAX, 0);
    if (ret != LZMA_OK)
    {
        close(fdi);
        close(fdo);
        log_error("Failed to initialize XZ decoder: code %d", ret);
        return -ENOMEM;
    }

    lzma_action action = LZMA_RUN;

    strm.next_out = buf_out;
    strm.avail_out = sizeof(buf_out);

    for (;;)
    {
        if (strm.avail_in == 0 && action == LZMA_RUN)
        {
            strm.next_in = buf_in;
            strm.avail_in = safe_read(fdi, buf_in, sizeof(buf_in));

            if (strm.avail_in < 0)
            {
                perror_msg("Failed to read source core file");
                close(fdi);
                close(fdo);
                lzma_end(&strm);
                return -1;
            }

            if (strm.avail_in == 0)
                action = LZMA_FINISH;
        }

        ret = lzma_code(&strm, action);

        if (strm.avail_out == 0 || ret == LZMA_STREAM_END)
        {
            const ssize_t n = sizeof(buf_out) - strm.avail_out;
            if (n != safe_write(fdo, buf_out, n))
            {
                perror_msg("Failed to write decompressed data");
                close(fdi);
                close(fdo);
                lzma_end(&strm);
                return -1;
            }

            if (ret == LZMA_STREAM_END)
            {
                log_debug("Successfully decompressed coredump.");
                break;
            }

            strm.next_out = buf_out;
            strm.avail_out = sizeof(buf_out);
        }
    }

    return 0;
#else /*HAVE_LZMA*/
    const char *cmd[] = { "xzcat", "-d", "-", NULL };
    return decompress_using_fork_execvp(cmd, fdi, fdo);
#endif /*HAVE_LZMA*/
}
Esempio n. 9
0
static int
decompress_fd_lz4(int fdi, int fdo)
{
#ifdef HAVE_LZ4
    enum { LZ4_DEC_BUF_SIZE = 64*1024u };

    LZ4F_decompressionContext_t ctx = NULL;
    LZ4F_errorCode_t c;
    char *buf = NULL;
    char *src = NULL;
    int r = 0;
    struct stat fdist;

    c = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
    if (LZ4F_isError(c))
    {
        log_debug("Failed to initialized LZ4: %s", LZ4F_getErrorName(c));
        r = -ENOMEM;
        goto cleanup;
    }

    buf = malloc(LZ4_DEC_BUF_SIZE);
    if (!buf)
    {
        r = -errno;
        goto cleanup;
    }

    if (fstat(fdi, &fdist) < 0)
    {
        r = -errno;
        log_debug("Failed to stat the input fd");
        goto cleanup;
    }

    src = mmap(NULL, fdist.st_size, PROT_READ, MAP_PRIVATE, fdi, 0);
    if (!src)
    {
        r = -errno;
        log_debug("Failed to mmap the input fd");
        goto cleanup;
    }

    off_t total_in = 0;
    while (fdist.st_size != total_in)
    {
        size_t used = fdist.st_size - total_in;
        size_t produced = LZ4_DEC_BUF_SIZE;

        c = LZ4F_decompress(ctx, buf, &produced, src + total_in, &used, NULL);
        if (LZ4F_isError(c))
        {
            log_debug("Failed to decode LZ4 block: %s", LZ4F_getErrorName(c));
            r = -EBADMSG;
            goto cleanup;
        }

        r = safe_write(fdo, buf, produced);
        if (r < 0)
        {
            log_debug("Failed to write decoded block");
            goto cleanup;
        }

        total_in += used;
    }
    r = 0;

cleanup:
    if (ctx != NULL)
        LZ4F_freeDecompressionContext(ctx);

    if (buf != NULL)
        free(buf);

    if (src != NULL)
        munmap(src, fdist.st_size);

    return r;
#else /*HAVE_LZ4*/
    const char *cmd[] = { "lz4", "-cd", "-", NULL};
    return decompress_using_fork_execvp(cmd, fdi, fdo);
#endif /*HAVE_LZ4*/
}
Esempio n. 10
0
static int fcgi_read_request(fcgi_request *req)
{
    fcgi_header hdr;
    int len, padding;
    unsigned char buf[FCGI_MAX_LENGTH+8];

    req->keep = 0;
    req->in_len = 0;
    req->out_hdr = NULL;
    req->out_pos = req->out_buf;
    zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1);

    if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
            hdr.version < FCGI_VERSION_1) {
        return 0;
    }

    len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
    padding = hdr.paddingLength;

    while (hdr.type == FCGI_STDIN && len == 0) {
        if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
                hdr.version < FCGI_VERSION_1) {
            return 0;
        }

        len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
        padding = hdr.paddingLength;
    }

    req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;

    if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
        char *val;

        if (safe_read(req, buf, len+padding) != len+padding) {
            return 0;
        }

        req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
        switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
        case FCGI_RESPONDER:
            val = strdup("RESPONDER");
            zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
            break;
        case FCGI_AUTHORIZER:
            val = strdup("AUTHORIZER");
            zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
            break;
        case FCGI_FILTER:
            val = strdup("FILTER");
            zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
            break;
        default:
            return 0;
        }

        if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
                hdr.version < FCGI_VERSION_1) {
            return 0;
        }

        len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
        padding = hdr.paddingLength;

        while (hdr.type == FCGI_PARAMS && len > 0) {
            if (safe_read(req, buf, len+padding) != len+padding) {
                req->keep = 0;
                return 0;
            }

            if (!fcgi_get_params(req, buf, buf+len)) {
                req->keep = 0;
                return 0;
            }

            if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
                    hdr.version < FCGI_VERSION_1) {
                req->keep = 0;
                return 0;
            }
            len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
            padding = hdr.paddingLength;
        }
    } else if (hdr.type == FCGI_GET_VALUES) {
        int j;
        unsigned char *p = buf + sizeof(fcgi_header);

        if (safe_read(req, buf, len+padding) != len+padding) {
            req->keep = 0;
            return 0;
        }

        if (!fcgi_get_params(req, buf, buf+len)) {
            req->keep = 0;
            return 0;
        }

        for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) {
            if (zend_hash_exists(&req->env, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].name_len+1) == 0) {
                sprintf((char*)p, "%c%c%s%c", fcgi_mgmt_vars[j].name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val);
                p += fcgi_mgmt_vars[j].name_len + 3;
            }
        }
        len = p - buf - sizeof(fcgi_header);
        len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
        if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
            req->keep = 0;
            return 0;
        }
        return 0;
    } else {
        return 0;
    }

    return 1;
}
Esempio n. 11
0
int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
{
    int limit, rest;

    if (len <= 0) {
        return 0;
    }

    if (req->out_hdr && req->out_hdr->type != type) {
        close_packet(req);
    }
#if 0
    /* Unoptimized, but clear version */
    rest = len;
    while (rest > 0) {
        limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);

        if (!req->out_hdr) {
            if (limit < sizeof(fcgi_header)) {
                if (!fcgi_flush(req, 0)) {
                    return -1;
                }
            }
            open_packet(req, type);
        }
        limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
        if (rest < limit) {
            memcpy(req->out_pos, str, rest);
            req->out_pos += rest;
            return len;
        } else {
            memcpy(req->out_pos, str, limit);
            req->out_pos += limit;
            rest -= limit;
            str += limit;
            if (!fcgi_flush(req, 0)) {
                return -1;
            }
        }
    }
#else
    /* Optimized version */
    limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
    if (!req->out_hdr) {
        limit -= sizeof(fcgi_header);
        if (limit < 0) limit = 0;
    }

    if (len < limit) {
        if (!req->out_hdr) {
            open_packet(req, type);
        }
        memcpy(req->out_pos, str, len);
        req->out_pos += len;
    } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) {
        if (!req->out_hdr) {
            open_packet(req, type);
        }
        if (limit > 0) {
            memcpy(req->out_pos, str, limit);
            req->out_pos += limit;
        }
        if (!fcgi_flush(req, 0)) {
            return -1;
        }
        if (len > limit) {
            open_packet(req, type);
            memcpy(req->out_pos, str + limit, len - limit);
            req->out_pos += len - limit;
        }
    } else {
        int pos = 0;
        int pad;

        close_packet(req);
        while ((len - pos) > 0xffff) {
            open_packet(req, type);
            fcgi_make_header(req->out_hdr, type, req->id, 0xfff8);
            req->out_hdr = NULL;
            if (!fcgi_flush(req, 0)) {
                return -1;
            }
            if (safe_write(req, str + pos, 0xfff8) != 0xfff8) {
                req->keep = 0;
                return -1;
            }
            pos += 0xfff8;
        }

        pad = (((len - pos) + 7) & ~7) - (len - pos);
        rest = pad ? 8 - pad : 0;

        open_packet(req, type);
        fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest);
        req->out_hdr = NULL;
        if (!fcgi_flush(req, 0)) {
            return -1;
        }
        if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) {
            req->keep = 0;
            return -1;
        }
        if (pad) {
            open_packet(req, type);
            memcpy(req->out_pos, str + len - rest,  rest);
            req->out_pos += rest;
        }
    }
#endif
    return len;
}
Esempio n. 12
0
int recv_sideband(const char *me, int in_stream, int out, int err)
{
	unsigned pf = strlen(PREFIX);
	unsigned sf;
	char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
	char *suffix, *term;
	int skip_pf = 0;

	memcpy(buf, PREFIX, pf);
	term = getenv("TERM");
	if (term && strcmp(term, "dumb"))
		suffix = ANSI_SUFFIX;
	else
		suffix = DUMB_SUFFIX;
	sf = strlen(suffix);

	while (1) {
		int band, len;
		len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX);
		if (len == 0)
			break;
		if (len < 1) {
			len = sprintf(buf, "%s: protocol error: no band designator\n", me);
			safe_write(err, buf, len);
			return SIDEBAND_PROTOCOL_ERROR;
		}
		band = buf[pf] & 0xff;
		len--;
		switch (band) {
		case 3:
			buf[pf] = ' ';
			buf[pf+1+len] = '\n';
			safe_write(err, buf, pf+1+len+1);
			return SIDEBAND_REMOTE_ERROR;
		case 2:
			buf[pf] = ' ';
			do {
				char *b = buf;
				int brk = 0;

				/*
				 * If the last buffer didn't end with a line
				 * break then we should not print a prefix
				 * this time around.
				 */
				if (skip_pf) {
					b += pf+1;
				} else {
					len += pf+1;
					brk += pf+1;
				}

				/* Look for a line break. */
				for (;;) {
					brk++;
					if (brk > len) {
						brk = 0;
						break;
					}
					if (b[brk-1] == '\n' ||
					    b[brk-1] == '\r')
						break;
				}

				/*
				 * Let's insert a suffix to clear the end
				 * of the screen line if a line break was
				 * found.  Also, if we don't skip the
				 * prefix, then a non-empty string must be
				 * present too.
				 */
				if (brk > (skip_pf ? 0 : (pf+1 + 1))) {
					char save[FIX_SIZE];
					memcpy(save, b + brk, sf);
					b[brk + sf - 1] = b[brk - 1];
					memcpy(b + brk - 1, suffix, sf);
					safe_write(err, b, brk + sf);
					memcpy(b + brk, save, sf);
					len -= brk;
				} else {
					int l = brk ? brk : len;
					safe_write(err, b, l);
					len -= l;
				}

				skip_pf = !brk;
				memmove(buf + pf+1, b + brk, len);
			} while (len);
			continue;
		case 1:
			safe_write(out, buf + pf+1, len);
			continue;
		default:
			len = sprintf(buf,
				      "%s: protocol error: bad band #%d\n",
				      me, band);
			safe_write(err, buf, len);
			return SIDEBAND_PROTOCOL_ERROR;
		}
	}
	return 0;
}
Esempio n. 13
0
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
	ucontext_t *ucontext = (ucontext_t*)context;
	pid_t dbg_pid;
	int fd[2];

	/* Make sure the effective uid is the real uid */
	if(getuid() != geteuid())
	{
		raise(signum);
		return;
	}

	safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
	if(pipe(fd) == -1)
	{
		safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
		raise(signum);
		return;
	}

	crash_info.signum = signum;
	crash_info.pid = getpid();
	crash_info.has_siginfo = !!siginfo;
	if(siginfo)
		crash_info.siginfo = *siginfo;
	if(cc_user_info)
		cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));

	/* Fork off to start a crash handler */
	switch((dbg_pid=fork()))
	{
		/* Error */
		case -1:
			safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
			raise(signum);
			return;

		case 0:
			dup2(fd[0], STDIN_FILENO);
			close(fd[0]);
			close(fd[1]);

			execl(argv0, argv0, crash_switch, NULL);

			safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
			_exit(1);

		default:
#ifdef __linux__
			prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
			safe_write(fd[1], &crash_info, sizeof(crash_info));
			close(fd[0]);
			close(fd[1]);

			/* Wait; we'll be killed when gdb is done */
			do {
				int status;
				if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
				   (WIFEXITED(status) || WIFSIGNALED(status)))
				{
					/* The debug process died before it could kill us */
					raise(signum);
					break;
				}
			} while(1);
	}
}
Esempio n. 14
0
int main(void) {

	int32_t	nready;
	uint8_t index_to;
	struct timeval timeout;

	/* settaggio della connessione TCP con l'applicazine fissa */
	to_app = setup_conn(SOCK_STREAM, AF_INET, LOCAL_LISTEN_PORT, (int8_t*) "INADDR_ANY", 0, 0, 1);
	/* accettazione della connessione proveniente dall'applicazione fissa */
	new_app_fd = listen_accept(to_app, &app_side);
	/* settaggio della connessione UDP con il monitor */
	udp_gate = setup_conn(SOCK_DGRAM, AF_INET, LOCAL_UDP_PORT, (int8_t*) "INADDR_ANY", 0, 0, 0);
	
	/* inizializzazione strutture */
	make_list(&port_list);
	clear_buffer(down_packets);
	clear_buffer(up_packets);
	udp_clear_buffer(to_app_packets);
	srand(getpid());
	/* inizializzazioni di default */
	last_uploaded = ID_START;
	actual_zero.tv_usec = actual_zero.tv_sec = 0;
	us_zero.tv_usec = us_zero.tv_sec = 0;
	index_to = BUFF_PACK_SIZE;	/* no timeout inizialmente */
	m_id_ports.type = 'C';
	m_id_ports.message = 0;
	last_notify = last_seq = 0;
	good_percentual = GOOD_P;

	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	FD_ZERO(&s_readfds);
	FD_ZERO(&s_writefds);

	FD_SET(new_app_fd, &readfds);	/* tanto prima aspetta un pacchetto da noi */
	FD_SET(udp_gate, &readfds);
	maxfds = (udp_gate > new_app_fd ? udp_gate : new_app_fd);

	for (;;) {

		s_readfds = readfds;
		s_writefds = writefds;
		nready = select(maxfds + 1, &s_readfds, &s_writefds, NULL, (index_to == BUFF_PACK_SIZE ? NULL : (&timeout)));
		if ((nready == ERROR) && (errno != EINTR)) {
			fprintf(stderr, "fatal error performing select. errno %s\n", strerror(errno));
			exit(EXIT_FAILURE);
		}
		if (FD_ISSET(new_app_fd, &s_readfds)) {
			uint8_t oldestpack, index;

			/* buffering dei pacchetti provenienti dall' applicazione */
			drop_expired(down_packets);
			safe_read(new_app_fd, DATA_BUFF_SIZE, data_app_fixed);
			/* evitiamo il possibile traboccamento di down_packets */
			if ((index = index_free_pack(down_packets)) == BUFF_PACK_SIZE) {
				oldestpack = oldest_pack(down_packets);
				clear_pack(down_packets, oldestpack);
				index = oldestpack;
			}
			memcpy(&(down_packets[index].udp_data.id_packet), data_app_fixed, sizeof(uint32_t));
			memcpy(&(down_packets[index].udp_data.data), &(data_app_fixed[4]), DATA_BUFF_SIZE - sizeof(uint32_t));
			down_packets[index].udp_data.type_packet = STANDARD;
			gettimeofday(&(down_packets[index].arrived), NULL);
			if (s_2_i(&us_zero) == 0)
				us_zero = down_packets[index].arrived;
			down_packets[index].udp_data.the_mighty_fix = s_2_i(&(down_packets[index].arrived)) - (s_2_i(&us_zero) + (INTER_PACKET * (down_packets[index].udp_data.id_packet - ID_FIRST_SENT)));
			down_packets[index].flag_to_send = NEW_ENTRY_FLAG;
			FD_SET(udp_gate, &writefds);
		}
		if (FD_ISSET(udp_gate, &s_writefds)) {
			uint8_t	index;
			struct errno_port ep;
			double rand_n;

			if ((index = first_pack_to_send(down_packets)) != BUFF_PACK_SIZE) {
				/* spedizione del pacchetto verso il monitor */
				ep.type_errno = EXIT_FAILURE;
				while ((ep.type_errno != EXIT_SUCCESS) && (ep.type_errno != EAGAIN) && (port_list != NULL)) {
					gettimeofday(&(down_packets[index].time_last_send), NULL);
					down_packets[index].udp_data.time_buffered = BUFFERED_TIME(down_packets[index]);
					ep = send_the_pack((int32_t*) &(down_packets[index]), STANDARD, udp_gate, port_list);
				/*	printf("utilizzato porta id: %u\n", ep.id_port); */
				}
			#ifdef O_DEBUG
				if (ep.type_errno == EXIT_SUCCESS) {
					printf("spedito il pacchetto con id %d\n", down_packets[index].udp_data.id_packet);
				}
			#endif
				RANDOM_N(rand_n);
				if ((rand_n > (good_percentual - 0)) && (down_packets[index].n_resending > 0)) {
					down_packets[index].flag_to_send = NACK_FLAG;	/* forza la riconsiderazione del pacchetto */
					down_packets[index].n_resending--;
				}
				if ((index = first_pack_to_send(down_packets)) == BUFF_PACK_SIZE)
					FD_CLR(udp_gate, &writefds);
			}
			else {
				FD_CLR(udp_gate, &writefds);
			}
		}
		if (FD_ISSET(udp_gate, &s_readfds)) {
			udp_packet tmp;
			struct sockaddr_in mon_side;
			
			/* ricezione dei dal monitor */
			general_recvfrom((int32_t *) &(tmp), sizeof(udp_packet), udp_gate, &mon_side);

			if (check_port(port_list, ntohs(mon_side.sin_port)) == FALSE) /* inserimento di una, forse, nuova porta monitor */
				insert_port(&port_list, ntohs(mon_side.sin_port));
			switch (tmp.type_packet) {
				case STANDARD: {
				#ifdef O_DEBUG
					printf("id pacchetto ricevuto: %d\n", tmp.id_packet);
				#endif
					up_packets[BUFF_PACK_SIZE - 1].udp_data = tmp;	/* speranza che sia vuoto per la legge di Gigio */
					gettimeofday(&(up_packets[BUFF_PACK_SIZE - 1].delivered), NULL);
					if ((actual_zero.tv_usec == 0) && (actual_zero.tv_sec == 0))	/* nuovo zero dell'opposto balancer */
						i_2_s(s_2_i(&(up_packets[BUFF_PACK_SIZE - 1].delivered)) - (INTER_PACKET * tmp.id_packet), &actual_zero);
					mighty_f_revenge(up_packets, BUFF_PACK_SIZE - 1, &actual_zero, 0);
					if (tmp.id_packet == (last_uploaded + 1)) {	/* e' il successivo */
						clear_pack(up_packets, BUFF_PACK_SIZE - 1);
						to_app_packets[index_udpfree_pack(to_app_packets)] = tmp;
						last_uploaded = tmp.id_packet;	/* aggiorno ultimo upload */
						check_inline_pack(up_packets, to_app_packets, &last_uploaded, tmp.id_packet);
						FD_SET(new_app_fd, &writefds);
					}
					else {
						if (tmp.id_packet > last_uploaded) {
							sort_buffer(up_packets);
						}
						else	/* in ritado abissale, drop */
							clear_pack(up_packets, BUFF_PACK_SIZE - 1);
					}
					break;
				}
				default : {		/* pacchetto di notifica */
					port_monitoring *ptmp = NULL;
					stat_notify *trick = (stat_notify*) &tmp;
				#ifdef O_DEBUG_N
					printf("pacchetto id: %d\n", tmp.id_packet);
					printf("pacchetto di notifica con porta id: %d\n", trick->id_port);
				#endif
				
					if ((last_notify < trick->id_notify) || (last_seq == trick->id_sequence)) { /* non e' in ritardo abissale */
						if ((trick->id_sequence < last_seq) || (trick->id_sequence > last_seq)) { /* nuova sequenza di notifiche */
							m_id_ports.message = trick->type_packet - NOTIFY_F;
							last_seq = trick->id_sequence;
						}
						last_notify = trick->id_notify;
						m_id_ports.message--; /* nuova notifica della stessa sequenza, decrementa contatore */
						m_id_ports.ports[m_id_ports.message] = trick->id_port + 1000;
						ptmp = find_port(port_list, trick->id_port + 1000); /* abbiamo spedito ID lato mobile, vogliamo quello fixed */
						if (ptmp == NULL) { /* porta di cui il fixed non era a conoscenza */
							if (m_id_ports.message == 0) {
							/* non ci sono piu' pacchetti di notifica, costruzione della lista delle porte aperte
							 * e reset-default per la prossima volta */
								m_id_ports.message = trick->type_packet - NOTIFY_F; /* lunghezza lista porte del mobile */
								build_act_ports(&port_list, &m_id_ports);
								m_id_ports.message = 0; /* reset per la prossima notifica */
								break;
							}
							insert_port(&port_list, trick->id_port + 1000);
							break; /* esce forzatamente dallo switch */
						}
						ptmp->not_to_fixed = *trick;	/* aggiorna la notifica */
						ptmp->last_tot_packets = ptmp->tot_packets - ptmp->medium_tot_packets;
						good_percentual = partial_pp_lost(port_list);
						ptmp->ack_packets += ptmp->not_to_fixed.n_received;
						ptmp->nack_packets = ptmp->tot_packets - ptmp->ack_packets;
						ptmp->medium_tot_packets = ptmp->tot_packets;
						mighty_f_ports(&port_list); /* calcolo performance delle porte */
						if (m_id_ports.message == 0) {
						/* non ci sono piu' pacchetti di notifica, costruzione della lista delle porte aperte
						* e reset-default per la prossima volta */
							m_id_ports.message = trick->type_packet - NOTIFY_F; /* lunghezza lista porte del mobile */
							build_act_ports(&port_list, &m_id_ports);
							m_id_ports.message = 0; /* reset per la prossima notifica */
						}
					}
				}
			}
		}
		if (FD_ISSET(new_app_fd, &s_writefds)) {
			memcpy(data_app_fixed, &(to_app_packets[0].id_packet), sizeof(uint32_t));
			memcpy(&(data_app_fixed[4]), &(to_app_packets[0].data), DATA_BUFF_SIZE - sizeof(uint32_t));
			safe_write(new_app_fd, DATA_BUFF_SIZE, data_app_fixed);
			udp_shift_pack(to_app_packets, 0);	/* clear e shift */
			if (to_app_packets[0].type_packet == FALSE)	/* non ce ne sono piu' */
				FD_CLR(new_app_fd, &writefds);
		}
		if (nready == 0) {	/* timeout espirato, nessun fd pronto */
			if (check_inline_pack(up_packets, to_app_packets, &last_uploaded, up_packets[0].udp_data.id_packet - 1))
				FD_SET(new_app_fd, &writefds);
		}
		index_to = BUFF_PACK_SIZE;
		timeout.tv_sec = timeout.tv_usec = 0;
		index_to = manage_timeout(up_packets, &timeout);
	}

	return 0;
}
Esempio n. 15
0
File: req.c Progetto: lipari/slurm
static int
_handle_suspend(int fd, slurmd_job_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;

	debug("_handle_suspend for job %u.%u",
	      job->jobid, job->stepid);

	debug3("  uid = %d", uid);
	if (!_slurm_authorized_user(uid)) {
		debug("job step suspend request from uid %ld for job %u.%u ",
		      (long)uid, job->jobid, job->stepid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	jobacct_gather_g_suspend_poll();

	/*
	 * Signal the container
	 */
	pthread_mutex_lock(&suspend_mutex);
	if (suspended) {
		rc = -1;
		errnum = ESLURMD_STEP_SUSPENDED;
		pthread_mutex_unlock(&suspend_mutex);
		goto done;
	} else {
		/* SIGTSTP is sent first to let MPI daemons stop their tasks,
		 * then wait 2 seconds, then send SIGSTOP to the spawned
		 * process's container to stop everything else.
		 *
		 * In some cases, 1 second has proven insufficient. Longer
		 * delays may help insure that all MPI tasks have been stopped
		 * (that depends upon the MPI implementaiton used), but will
		 * also permit longer time periods when more than one job can
		 * be running on each resource (not good). */
		if (slurm_container_signal(job->cont_id, SIGTSTP) < 0) {
			verbose("Error suspending %u.%u (SIGTSTP): %m",
				job->jobid, job->stepid);
		} else
			sleep(2);

		if (slurm_container_signal(job->cont_id, SIGSTOP) < 0) {
			verbose("Error suspending %u.%u (SIGSTOP): %m",
				job->jobid, job->stepid);
		} else {
			verbose("Suspended %u.%u", job->jobid, job->stepid);
		}
		suspended = true;
	}
	pthread_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errno */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 16
0
File: task.c Progetto: npe9/slurm
/*
 * Process TaskProlog output
 * "export NAME=value"	adds environment variables
 * "unset  NAME"	clears an environment variable
 * "print  <whatever>"	writes that to the job's stdout
 */
static void _proc_stdout(char *buf, stepd_step_rec_t *job)
{
	bool end_buf = false;
	int len;
	char *buf_ptr, *name_ptr, *val_ptr;
	char *end_line, *equal_ptr;
	char ***env = &job->env;

	buf_ptr = buf;
	while (buf_ptr[0]) {
		end_line = strchr(buf_ptr, '\n');
		if (!end_line) {
			end_line = buf_ptr + strlen(buf_ptr);
			end_buf = true;
		}
		if (!strncmp(buf_ptr, "print ", 6)) {
			buf_ptr += 6;
			while (isspace(buf_ptr[0]))
				buf_ptr++;
			len = end_line - buf_ptr + 1;
			safe_write(1, buf_ptr, len);
		} else if (!strncmp(buf_ptr, "export ",7)) {
			name_ptr = buf_ptr + 7;
			while (isspace(name_ptr[0]))
				name_ptr++;
			equal_ptr = strchr(name_ptr, '=');
			if (!equal_ptr || (equal_ptr > end_line))
				goto rwfail;
			val_ptr = equal_ptr + 1;
			while (isspace(equal_ptr[-1]))
				equal_ptr--;
			equal_ptr[0] = '\0';
			end_line[0] = '\0';
			if (!strcmp(name_ptr, "SLURM_PROLOG_CPU_MASK")) {
				job->cpu_bind_type = CPU_BIND_MASK;
				xfree(job->cpu_bind);
				job->cpu_bind = xstrdup(val_ptr);
				if (task_g_pre_launch(job)) {
					error("Failed SLURM_PROLOG_CPU_MASK "
					      "setup");
					exit(1);
				}
			}
			debug("export name:%s:val:%s:", name_ptr, val_ptr);
			if (setenvf(env, name_ptr, "%s", val_ptr)) {
				error("Unable to set %s environment variable",
				      buf_ptr);
			}
			equal_ptr[0] = '=';
			if (end_buf)
				end_line[0] = '\0';
			else
				end_line[0] = '\n';
		} else if (!strncmp(buf_ptr, "unset ", 6)) {
			name_ptr = buf_ptr + 6;
			while (isspace(name_ptr[0]))
				name_ptr++;
			if ((name_ptr[0] == '\n') || (name_ptr[0] == '\0'))
				goto rwfail;
			while (isspace(end_line[-1]))
				end_line--;
			end_line[0] = '\0';
			debug(" unset name:%s:", name_ptr);
			unsetenvp(*env, name_ptr);
			if (end_buf)
				end_line[0] = '\0';
			else
				end_line[0] = '\n';
		}

rwfail:		 /* process rest of script output */
		if (end_buf)
			break;
		buf_ptr = end_line + 1;
	}
	return;
}
Esempio n. 17
0
File: req.c Progetto: lipari/slurm
static int
_handle_signal_process_group(int fd, slurmd_job_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int signal;

	debug3("_handle_signal_process_group for job %u.%u",
	      job->jobid, job->stepid);

	safe_read(fd, &signal, sizeof(int));

	debug3("  uid = %d", uid);
	if (uid != job->uid && !_slurm_authorized_user(uid)) {
		debug("kill req from uid %ld for job %u.%u owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = EPERM;
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (job->pgid <= (pid_t)1) {
		debug ("step %u.%u invalid [jmgr_pid:%d pgid:%u]",
		       job->jobid, job->stepid, job->jmgr_pid, job->pgid);
		rc = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	/*
	 * Signal the process group
	 */
	pthread_mutex_lock(&suspend_mutex);
	if (suspended && (signal != SIGKILL)) {
		rc = ESLURMD_STEP_SUSPENDED;
		pthread_mutex_unlock(&suspend_mutex);
		goto done;
	}

	/*
	 * Print a message in the step output before killing when
	 * SIGTERM or SIGKILL are sent
	 */
	if ((signal == SIGTERM) || (signal == SIGKILL)) {
		time_t now = time(NULL);
		char entity[24], time_str[24];
		if (job->stepid == SLURM_BATCH_SCRIPT) {
			snprintf(entity, sizeof(entity), "JOB %u", job->jobid);
		} else {
			snprintf(entity, sizeof(entity), "STEP %u.%u",
				 job->jobid, job->stepid);
		}
		slurm_make_time_str(&now, time_str, sizeof(time_str));

		error("*** %s KILLED AT %s WITH SIGNAL %u ***",
		      entity, time_str, signal);
	}

	if (killpg(job->pgid, signal) == -1) {
		rc = -1;
		verbose("Error sending signal %d to %u.%u, pgid %d: %m",
			signal, job->jobid, job->stepid, job->pgid);
	} else {
		verbose("Sent signal %d to %u.%u, pgid %d",
			signal, job->jobid, job->stepid, job->pgid);
	}
	pthread_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code */
	safe_write(fd, &rc, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 18
0
int chat_main(int argc UNUSED_PARAM, char **argv)
{
	int record_fd = -1;
	bool echo = 0;
	// collection of device replies which cause unconditional termination
	llist_t *aborts = NULL;
	// inactivity period
	int timeout = DEFAULT_CHAT_TIMEOUT;
	// maximum length of abort string
#if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN
	size_t max_abort_len = 0;
#else
#define max_abort_len MAX_ABORT_LEN
#endif
#if ENABLE_FEATURE_CHAT_TTY_HIFI
	struct termios tio0, tio;
#endif
	// directive names
	enum {
		DIR_HANGUP = 0,
		DIR_ABORT,
#if ENABLE_FEATURE_CHAT_CLR_ABORT
		DIR_CLR_ABORT,
#endif
		DIR_TIMEOUT,
		DIR_ECHO,
		DIR_SAY,
		DIR_RECORD,
	};

	// make x* functions fail with correct exitcode
	xfunc_error_retval = ERR_IO;

	// trap vanilla signals to prevent process from being killed suddenly
	bb_signals(0
		+ (1 << SIGHUP)
		+ (1 << SIGINT)
		+ (1 << SIGTERM)
		+ (1 << SIGPIPE)
		, signal_handler);

#if ENABLE_FEATURE_CHAT_TTY_HIFI
//TODO: use set_termios_to_raw()
	tcgetattr(STDIN_FILENO, &tio);
	tio0 = tio;
	cfmakeraw(&tio);
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
#endif

#if ENABLE_FEATURE_CHAT_SWALLOW_OPTS
	getopt32(argv, "vVsSE");
	argv += optind;
#else
	argv++; // goto first arg
#endif
	// handle chat expect-send pairs
	while (*argv) {
		// directive given? process it
		int key = index_in_strings(
			"HANGUP\0" "ABORT\0"
#if ENABLE_FEATURE_CHAT_CLR_ABORT
			"CLR_ABORT\0"
#endif
			"TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0"
			, *argv
		);
		if (key >= 0) {
			bool onoff;
			// cache directive value
			char *arg = *++argv;

			if (!arg) {
#if ENABLE_FEATURE_CHAT_TTY_HIFI
				tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
#endif
				bb_show_usage();
			}
			// OFF -> 0, anything else -> 1
			onoff = (0 != strcmp("OFF", arg));
			// process directive
			if (DIR_HANGUP == key) {
				// turn SIGHUP on/off
				signal(SIGHUP, onoff ? signal_handler : SIG_IGN);
			} else if (DIR_ABORT == key) {
				// append the string to abort conditions
#if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN
				size_t len = strlen(arg);
				if (len > max_abort_len)
					max_abort_len = len;
#endif
				llist_add_to_end(&aborts, arg);
#if ENABLE_FEATURE_CHAT_CLR_ABORT
			} else if (DIR_CLR_ABORT == key) {
				llist_t *l;
				// remove the string from abort conditions
				// N.B. gotta refresh maximum length too...
# if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN
				max_abort_len = 0;
# endif
				for (l = aborts; l; l = l->link) {
# if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN
					size_t len = strlen(l->data);
# endif
					if (strcmp(arg, l->data) == 0) {
						llist_unlink(&aborts, l);
						continue;
					}
# if ENABLE_FEATURE_CHAT_VAR_ABORT_LEN
					if (len > max_abort_len)
						max_abort_len = len;
# endif
				}
#endif
			} else if (DIR_TIMEOUT == key) {
				// set new timeout
				// -1 means OFF
				timeout = atoi(arg) * 1000;
				// 0 means default
				// >0 means value in msecs
				if (!timeout)
					timeout = DEFAULT_CHAT_TIMEOUT;
			} else if (DIR_ECHO == key) {
				// turn echo on/off
				// N.B. echo means dumping device input/output to stderr
				echo = onoff;
			} else if (DIR_RECORD == key) {
				// turn record on/off
				// N.B. record means dumping device input to a file
					// close previous record_fd
				if (record_fd > 0)
					close(record_fd);
				// N.B. do we have to die here on open error?
				record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1;
			} else if (DIR_SAY == key) {
				// just print argument verbatim
				// TODO: should we use full_write() to avoid unistd/stdio conflict?
				bb_error_msg("%s", arg);
			}
			// next, please!
			argv++;
		// ordinary expect-send pair!
		} else {
			//-----------------------
			// do expect
			//-----------------------
			int expect_len;
			size_t buf_len = 0;
			size_t max_len = max_abort_len;

			struct pollfd pfd;
#if ENABLE_FEATURE_CHAT_NOFAIL
			int nofail = 0;
#endif
			char *expect = *argv++;

			// sanity check: shall we really expect something?
			if (!expect)
				goto expect_done;

#if ENABLE_FEATURE_CHAT_NOFAIL
			// if expect starts with -
			if ('-' == *expect) {
				// swallow -
				expect++;
				// and enter nofail mode
				nofail++;
			}
#endif

#ifdef ___TEST___BUF___ // test behaviour with a small buffer
#	undef COMMON_BUFSIZE
#	define COMMON_BUFSIZE 6
#endif
			// expand escape sequences in expect
			expect_len = unescape(expect, &expect_len /*dummy*/);
			if (expect_len > max_len)
				max_len = expect_len;
			// sanity check:
			// we should expect more than nothing but not more than input buffer
			// TODO: later we'll get rid of fixed-size buffer
			if (!expect_len)
				goto expect_done;
			if (max_len >= COMMON_BUFSIZE) {
				exitcode = ERR_MEM;
				goto expect_done;
			}

			// get reply
			pfd.fd = STDIN_FILENO;
			pfd.events = POLLIN;
			while (!exitcode
			    && poll(&pfd, 1, timeout) > 0
			    && (pfd.revents & POLLIN)
			) {
				llist_t *l;
				ssize_t delta;
#define buf bb_common_bufsiz1
				setup_common_bufsiz();

				// read next char from device
				if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
					// dump device input if RECORD fname
					if (record_fd > 0) {
						full_write(record_fd, buf+buf_len, 1);
					}
					// dump device input if ECHO ON
					if (echo) {
//						if (buf[buf_len] < ' ') {
//							full_write(STDERR_FILENO, "^", 1);
//							buf[buf_len] += '@';
//						}
						full_write(STDERR_FILENO, buf+buf_len, 1);
					}
					buf_len++;
					// move input frame if we've reached higher bound
					if (buf_len > COMMON_BUFSIZE) {
						memmove(buf, buf+buf_len-max_len, max_len);
						buf_len = max_len;
					}
				}
				// N.B. rule of thumb: values being looked for can
				// be found only at the end of input buffer
				// this allows to get rid of strstr() and memmem()

				// TODO: make expect and abort strings processed uniformly
				// abort condition is met? -> bail out
				for (l = aborts, exitcode = ERR_ABORT; l; l = l->link, ++exitcode) {
					size_t len = strlen(l->data);
					delta = buf_len-len;
					if (delta >= 0 && !memcmp(buf+delta, l->data, len))
						goto expect_done;
				}
				exitcode = ERR_OK;

				// expected reply received? -> goto next command
				delta = buf_len - expect_len;
				if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
					goto expect_done;
#undef buf
			} /* while (have data) */

			// device timed out or unexpected reply received
			exitcode = ERR_TIMEOUT;
 expect_done:
#if ENABLE_FEATURE_CHAT_NOFAIL
			// on success and when in nofail mode
			// we should skip following subsend-subexpect pairs
			if (nofail) {
				if (!exitcode) {
					// find last send before non-dashed expect
					while (*argv && argv[1] && '-' == argv[1][0])
						argv += 2;
					// skip the pair
					// N.B. do we really need this?!
					if (!*argv++ || !*argv++)
						break;
				}
				// nofail mode also clears all but IO errors (or signals)
				if (ERR_IO != exitcode)
					exitcode = ERR_OK;
			}
#endif
			// bail out unless we expected successfully
			if (exitcode)
				break;

			//-----------------------
			// do send
			//-----------------------
			if (*argv) {
#if ENABLE_FEATURE_CHAT_IMPLICIT_CR
				int nocr = 0; // inhibit terminating command with \r
#endif
				char *loaded = NULL; // loaded command
				size_t len;
				char *buf = *argv++;

				// if command starts with @
				// load "real" command from file named after @
				if ('@' == *buf) {
					// skip the @ and any following white-space
					trim(++buf);
					buf = loaded = xmalloc_xopen_read_close(buf, NULL);
				}
				// expand escape sequences in command
				len = unescape(buf, &nocr);

				// send command
				alarm(timeout);
				pfd.fd = STDOUT_FILENO;
				pfd.events = POLLOUT;
				while (len && !exitcode
				    && poll(&pfd, 1, -1) > 0
				    && (pfd.revents & POLLOUT)
				) {
#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
					// "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
					// "\\K" means send BREAK
					char c = *buf;
					if ('\\' == c) {
						c = *++buf;
						if ('d' == c) {
							sleep(1);
							len--;
							continue;
						}
						if ('p' == c) {
							usleep(10000);
							len--;
							continue;
						}
						if ('K' == c) {
							tcsendbreak(STDOUT_FILENO, 0);
							len--;
							continue;
						}
						buf--;
					}
					if (safe_write(STDOUT_FILENO, buf, 1) != 1)
						break;
					len--;
					buf++;
#else
					len -= full_write(STDOUT_FILENO, buf, len);
#endif
				} /* while (can write) */
				alarm(0);

				// report I/O error if there still exists at least one non-sent char
				if (len)
					exitcode = ERR_IO;

				// free loaded command (if any)
				if (loaded)
					free(loaded);
#if ENABLE_FEATURE_CHAT_IMPLICIT_CR
				// or terminate command with \r (if not inhibited)
				else if (!nocr)
					xwrite(STDOUT_FILENO, "\r", 1);
#endif
				// bail out unless we sent command successfully
				if (exitcode)
					break;
			} /* if (*argv) */
		}
	} /* while (*argv) */

#if ENABLE_FEATURE_CHAT_TTY_HIFI
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
#endif

	return exitcode;
}
Esempio n. 19
0
static int safe_puts(char * s)
{
	return safe_write(s, strlen(s));
}
Esempio n. 20
0
int
writePcmData (PcmDevice *pcm, const unsigned char *buffer, int count) {
  return safe_write(pcm->socket, buffer, count) != -1;
}
Esempio n. 21
0
static int
_handle_attach(int fd, stepd_step_rec_t *job, uid_t uid)
{
	srun_info_t *srun;
	int rc = SLURM_SUCCESS;

	debug("_handle_attach for job %u.%u", job->jobid, job->stepid);

	srun       = xmalloc(sizeof(srun_info_t));
	srun->key  = (srun_key_t *)xmalloc(SLURM_IO_KEY_SIZE);

	debug("sizeof(srun_info_t) = %d, sizeof(slurm_addr_t) = %d",
	      (int) sizeof(srun_info_t), (int) sizeof(slurm_addr_t));
	safe_read(fd, &srun->ioaddr, sizeof(slurm_addr_t));
	safe_read(fd, &srun->resp_addr, sizeof(slurm_addr_t));
	safe_read(fd, srun->key, SLURM_IO_KEY_SIZE);
	safe_read(fd, &srun->protocol_version, sizeof(int));

	if (!srun->protocol_version)
		srun->protocol_version = (uint16_t)NO_VAL;
	/*
	 * Check if jobstep is actually running.
	 */
	if (job->state != SLURMSTEPD_STEP_RUNNING) {
		rc = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	/*
	 * At the moment, it only makes sense for the slurmd to make this
	 * call, so only _slurm_authorized_user is allowed.
	 */
	if (!_slurm_authorized_user(uid)) {
		error("uid %ld attempt to attach to job %u.%u owned by %ld",
		      (long) uid, job->jobid, job->stepid, (long)job->uid);
		rc = EPERM;
		goto done;
	}

	list_prepend(job->sruns, (void *) srun);
	rc = io_client_connect(srun, job);
	debug("  back from io_client_connect, rc = %d", rc);
done:
	/* Send the return code */
	safe_write(fd, &rc, sizeof(int));

	debug("  in _handle_attach rc = %d", rc);
	if (rc == SLURM_SUCCESS) {
		/* Send response info */
		uint32_t *pids, *gtids;
		int len, i;

		debug("  in _handle_attach sending response info");
		len = job->node_tasks * sizeof(uint32_t);
		pids = xmalloc(len);
		gtids = xmalloc(len);

		if (job->task != NULL) {
			for (i = 0; i < job->node_tasks; i++) {
				if (job->task[i] == NULL)
					continue;
				pids[i] = (uint32_t)job->task[i]->pid;
				gtids[i] = job->task[i]->gtid;
			}
		}

		safe_write(fd, &job->node_tasks, sizeof(uint32_t));
		safe_write(fd, pids, len);
		safe_write(fd, gtids, len);
		xfree(pids);
		xfree(gtids);

		for (i = 0; i < job->node_tasks; i++) {
			if (job->task[i] && job->task[i]->argv) {
				len = strlen(job->task[i]->argv[0]) + 1;
				safe_write(fd, &len, sizeof(int));
				safe_write(fd, job->task[i]->argv[0], len);
			} else {
				len = 0;
				safe_write(fd, &len, sizeof(int));
			}
		}
	}

	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 22
0
File: utils.c Progetto: jonquach/ftp
void	exit_write(char *str)
{
  safe_write(STDOUT, str);
  exit(EXIT_FAILURE);
}
Esempio n. 23
0
static int
_handle_resume(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	uint16_t job_core_spec = (uint16_t) NO_VAL;

	safe_read(fd, &job_core_spec, sizeof(uint16_t));

	debug("_handle_resume for step:%u.%u uid:%ld core_spec:%u",
	      job->jobid, job->stepid, (long)uid, job_core_spec);

	if (!_slurm_authorized_user(uid)) {
		debug("job step resume request from uid %ld for job %u.%u ",
		      (long)uid, job->jobid, job->stepid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	acct_gather_resume_poll();
	/*
	 * Signal the container
	 */
	slurm_mutex_lock(&suspend_mutex);
	if (!suspended) {
		rc = -1;
		errnum = ESLURMD_STEP_NOTSUSPENDED;
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	} else {
		if (!job->batch && switch_g_job_step_pre_resume(job))
			error("switch_g_job_step_pre_resume: %m");
		if (!job->batch && core_spec_g_resume(job->cont_id,
						      job_core_spec))
			error("core_spec_g_resume: %m");
		if (proctrack_g_signal(job->cont_id, SIGCONT) < 0) {
			verbose("Error resuming %u.%u: %m",
				job->jobid, job->stepid);
		} else {
			verbose("Resumed %u.%u", job->jobid, job->stepid);
		}
		suspended = false;
	}
	if (!job->batch && switch_g_job_step_post_resume(job))
		error("switch_g_job_step_post_resume: %m");
	/* set the cpu frequencies if cpu_freq option used */
	if (job->cpu_freq_min != NO_VAL || job->cpu_freq_max != NO_VAL ||
	    job->cpu_freq_gov != NO_VAL) {
		cpu_freq_set(job);
	}

	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errno */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 24
0
static int receive(/*int read_fd, */int file_fd)
{
	unsigned char blockBuf[1024];
	unsigned blockLength = 0;
	unsigned errors = 0;
	unsigned wantBlockNo = 1;
	unsigned length = 0;
	int do_crc = 1;
	char reply_char;
	unsigned timeout = TIMEOUT_LONG;

	/* Flush pending input */
	tcflush(read_fd, TCIFLUSH);

	/* Ask for CRC; if we get errors, we will go with checksum */
	reply_char = 'C';
	full_write(write_fd, &reply_char, 1);

	for (;;) {
		int blockBegin;
		int blockNo, blockNoOnesCompl;
		int cksum_or_crc;
		unsigned expected;
		int i, j;

		blockBegin = read_byte(timeout);
		if (blockBegin < 0)
			goto timeout;

		/* If last block, remove padding */
		if (blockBegin == EOT) {
			/* Data blocks can be padded with ^Z characters */
			/* This code tries to detect and remove them */
			if (blockLength >= 3
			 && blockBuf[blockLength - 1] == PAD
			 && blockBuf[blockLength - 2] == PAD
			 && blockBuf[blockLength - 3] == PAD
			) {
				while (blockLength
				    && blockBuf[blockLength - 1] == PAD
				) {
					blockLength--;
				}
			}
		}
		/* Write previously received block */
		errno = 0;
		if (full_write(file_fd, blockBuf, blockLength) != blockLength) {
			bb_perror_msg(bb_msg_write_error);
			goto fatal;
		}

		timeout = TIMEOUT;
		reply_char = NAK;

		switch (blockBegin) {
		case SOH:
		case STX:
			break;
		case EOT:
			reply_char = ACK;
			full_write(write_fd, &reply_char, 1);
			return length;
		default:
			goto error;
		}

		/* Block no */
		blockNo = read_byte(TIMEOUT);
		if (blockNo < 0)
			goto timeout;

		/* Block no, in one's complement form */
		blockNoOnesCompl = read_byte(TIMEOUT);
		if (blockNoOnesCompl < 0)
			goto timeout;

		if (blockNo != (255 - blockNoOnesCompl)) {
			bb_error_msg("bad block ones compl");
			goto error;
		}

		blockLength = (blockBegin == SOH) ? 128 : 1024;

		for (i = 0; i < blockLength; i++) {
			int cc = read_byte(TIMEOUT);
			if (cc < 0)
				goto timeout;
			blockBuf[i] = cc;
		}

		cksum_or_crc = read_byte(TIMEOUT);
		if (cksum_or_crc < 0)
			goto timeout;
		if (do_crc) {
			cksum_or_crc = (cksum_or_crc << 8) | read_byte(TIMEOUT);
			if (cksum_or_crc < 0)
				goto timeout;
		}

		if (blockNo == ((wantBlockNo - 1) & 0xff)) {
			/* a repeat of the last block is ok, just ignore it. */
			/* this also ignores the initial block 0 which is */
			/* meta data. */
			blockLength = 0;
			goto next;
		}
		if (blockNo != (wantBlockNo & 0xff)) {
			bb_error_msg("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo);
			goto error;
		}

		expected = 0;
		if (do_crc) {
			for (i = 0; i < blockLength; i++) {
				expected = expected ^ blockBuf[i] << 8;
				for (j = 0; j < 8; j++) {
					if (expected & 0x8000)
						expected = (expected << 1) ^ 0x1021;
					else
						expected = (expected << 1);
				}
			}
			expected &= 0xffff;
		} else {
			for (i = 0; i < blockLength; i++)
				expected += blockBuf[i];
			expected &= 0xff;
		}
		if (cksum_or_crc != expected) {
			bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x"
					: "checksum error, expected 0x%02x, got 0x%02x",
				expected, cksum_or_crc);
			goto error;
		}

		wantBlockNo++;
		length += blockLength;
 next:
		errors = 0;
		reply_char = ACK;
		full_write(write_fd, &reply_char, 1);
		continue;
 error:
 timeout:
		blockLength = 0;
		errors++;
		if (errors == MAXERRORS) {
			/* Abort */

			/* If were asking for crc, try again w/o crc */
			if (reply_char == 'C') {
				reply_char = NAK;
				errors = 0;
				do_crc = 0;
				goto timeout;
			}
			bb_error_msg("too many errors; giving up");
 fatal:
			/* 5 CAN followed by 5 BS. Don't try too hard... */
			safe_write(write_fd, "\030\030\030\030\030\010\010\010\010\010", 10);
			return -1;
		}

		/* Flush pending input */
		tcflush(read_fd, TCIFLUSH);

		full_write(write_fd, &reply_char, 1);
	} /* for (;;) */
}
Esempio n. 25
0
static void *
_handle_accept(void *arg)
{
	/*struct request_params *param = (struct request_params *)arg;*/
	int fd = ((struct request_params *)arg)->fd;
	stepd_step_rec_t *job = ((struct request_params *)arg)->job;
	int req;
	int len;
	Buf buffer = NULL;
	void *auth_cred;
	int rc;
	uid_t uid;
	gid_t gid;
	char *auth_info;

	debug3("Entering _handle_accept (new thread)");
	xfree(arg);

	safe_read(fd, &req, sizeof(int));
	if (req != REQUEST_CONNECT) {
		error("First message must be REQUEST_CONNECT");
		goto fail;
	}

	safe_read(fd, &len, sizeof(int));
	buffer = init_buf(len);
	safe_read(fd, get_buf_data(buffer), len);

	/* Unpack and verify the auth credential */
	auth_cred = g_slurm_auth_unpack(buffer);
	if (auth_cred == NULL) {
		error("Unpacking authentication credential: %s",
		      g_slurm_auth_errstr(g_slurm_auth_errno(NULL)));
		free_buf(buffer);
		goto fail;
	}
	auth_info = slurm_get_auth_info();
	rc = g_slurm_auth_verify(auth_cred, NULL, 2, auth_info);
	if (rc != SLURM_SUCCESS) {
		error("Verifying authentication credential: %s",
		      g_slurm_auth_errstr(g_slurm_auth_errno(auth_cred)));
		xfree(auth_info);
		(void) g_slurm_auth_destroy(auth_cred);
		FREE_NULL_BUFFER(buffer);
		goto fail;
	}

	/* Get the uid & gid from the credential, then destroy it. */
	uid = g_slurm_auth_get_uid(auth_cred, auth_info);
	gid = g_slurm_auth_get_gid(auth_cred, auth_info);
	xfree(auth_info);
	debug3("  Identity: uid=%d, gid=%d", uid, gid);
	g_slurm_auth_destroy(auth_cred);
	FREE_NULL_BUFFER(buffer);

	rc = SLURM_PROTOCOL_VERSION;
	safe_write(fd, &rc, sizeof(int));

	while (1) {
		rc = _handle_request(fd, job, uid, gid);
		if (rc != SLURM_SUCCESS)
			break;
	}

	if (close(fd) == -1)
		error("Closing accepted fd: %m");

	slurm_mutex_lock(&message_lock);
	message_connections--;
	slurm_cond_signal(&message_cond);
	slurm_mutex_unlock(&message_lock);

	debug3("Leaving  _handle_accept");
	return NULL;

fail:
	rc = SLURM_FAILURE;
	safe_write(fd, &rc, sizeof(int));
rwfail:
	if (close(fd) == -1)
		error("Closing accepted fd after error: %m");
	debug("Leaving  _handle_accept on an error");
	FREE_NULL_BUFFER(buffer);
	return NULL;
}
Esempio n. 26
0
int
logger(struct ProxyContext_ * const context,
       const int crit, const char * const format, ...)
{
    static char         previous_line[MAX_LOG_LINE];
    static time_t       last_log_ts = (time_t) 0;
    static unsigned int burst_counter = 0U;
    char        line[MAX_LOG_LINE];
    va_list     va;
    const char *urgency;
    time_t      now = time(NULL);
    size_t      len;
    int         log_fd;

#ifndef DEBUG
    if (crit == LOG_DEBUG) {
        return 0;
    }
#endif
    switch (crit) {
    case LOG_INFO:
        urgency = "[INFO] ";
        break;
    case LOG_WARNING:
        urgency = "[WARNING] ";
        break;
    case LOG_ERR:
        urgency = "[ERROR] ";
        break;
    case LOG_NOTICE:
        urgency = "[NOTICE] ";
        break;
    case LOG_DEBUG:
        urgency = "[DEBUG] ";
        break;
    default:
        urgency = "";
    }
    va_start(va, format);
    len = (size_t) evutil_vsnprintf(line, sizeof line, format, va);
    va_end(va);

    if (len >= sizeof line) {
        assert(sizeof line > (size_t) 0U);
        len = sizeof line - (size_t) 1U;
    }
    line[len++] = 0;
#ifndef _WIN32
    if (context != NULL && context->log_fd == -1 && context->daemonize) {
        syslog(crit, "%s", line);
        return 0;
    }
#endif
    if (memcmp(previous_line, line, len) == 0) {
        burst_counter++;
        if (burst_counter > LOGGER_ALLOWED_BURST_FOR_IDENTICAL_LOG_ENTRIES &&
            now - last_log_ts < LOGGER_DELAY_BETWEEN_IDENTICAL_LOG_ENTRIES) {
            return 1;
        }
    } else {
        burst_counter = 0U;
    }
    last_log_ts = now;
    assert(sizeof previous_line >= sizeof line);
    memcpy(previous_line, line, len);
    if (context == NULL || context->log_fd == -1) {
        log_fd = STDERR_FILENO;
    } else {
        log_fd = context->log_fd;
    }
#ifndef _WIN32
    safe_write(log_fd, urgency, strlen(urgency), LOG_WRITE_TIMEOUT);
    safe_write(log_fd, line, strlen(line), LOG_WRITE_TIMEOUT);
    safe_write(log_fd, "\n", (size_t) 1U, LOG_WRITE_TIMEOUT);
#else
    (void) log_fd;
    printf("%s%s\n", urgency, line);
    fflush(stdout);
#endif

    return 0;
}
Esempio n. 27
0
static int
_handle_signal_container(int fd, stepd_step_rec_t *job, uid_t uid)
{
	int rc = SLURM_SUCCESS;
	int errnum = 0;
	int sig;
	static int msg_sent = 0;
	char *ptr = NULL;
	int target_node_id = 0;
	stepd_step_task_info_t *task;
	uint32_t i;
	uint32_t flag;
	uint32_t signal;

	safe_read(fd, &signal, sizeof(int));
	flag = signal >> 24;
	sig = signal & 0xfff;

	debug("_handle_signal_container for step=%u.%u uid=%d signal=%d",
	      job->jobid, job->stepid, (int) uid, sig);
	if ((uid != job->uid) && !_slurm_authorized_user(uid)) {
		error("signal container req from uid %ld for step=%u.%u "
		      "owned by uid %ld",
		      (long)uid, job->jobid, job->stepid, (long)job->uid);
		rc = -1;
		errnum = EPERM;
		goto done;
	}

	/*
	 * Sanity checks
	 */
	if (job->cont_id == 0) {
		debug ("step %u.%u invalid container [cont_id:%"PRIu64"]",
			job->jobid, job->stepid, job->cont_id);
		rc = -1;
		errnum = ESLURMD_JOB_NOTRUNNING;
		goto done;
	}

	if ((sig == SIGTERM) || (sig == SIGKILL)) {
		/* cycle thru the tasks and mark those that have not
		 * called abort and/or terminated as killed_by_cmd
		 */
		for (i = 0; i < job->node_tasks; i++) {
			if (NULL == (task = job->task[i])) {
				continue;
			}
			if (task->aborted || task->exited) {
				continue;
			}
			/* mark that this task is going to be killed by
			 * cmd so we ignore its exit status - otherwise,
			 * we will probably report the final exit status
			 * as SIGKILL
			 */
			task->killed_by_cmd = true;
		}
	}

	ptr = getenvp(job->env, "SLURM_STEP_KILLED_MSG_NODE_ID");
	if (ptr)
		target_node_id = atoi(ptr);
	if ((job->stepid != SLURM_EXTERN_CONT) &&
	    (job->nodeid == target_node_id) && (msg_sent == 0) &&
	    (job->state < SLURMSTEPD_STEP_ENDING)) {
		time_t now = time(NULL);
		char entity[24], time_str[24];

		if (job->stepid == SLURM_BATCH_SCRIPT) {
			snprintf(entity, sizeof(entity), "JOB %u", job->jobid);
		} else {
			snprintf(entity, sizeof(entity), "STEP %u.%u",
				 job->jobid, job->stepid);
		}
		slurm_make_time_str(&now, time_str, sizeof(time_str));

		/* Not really errors,
		 * but we want messages displayed by default */
		if (sig == SIG_TIME_LIMIT) {
			error("*** %s ON %s CANCELLED AT %s DUE TO TIME LIMIT ***",
			      entity, job->node_name, time_str);
			msg_sent = 1;
		} else if (sig == SIG_PREEMPTED) {
			error("*** %s ON %s CANCELLED AT %s DUE TO PREEMPTION ***",
			      entity, job->node_name, time_str);
			msg_sent = 1;
		} else if (sig == SIG_NODE_FAIL) {
			error("*** %s ON %s CANCELLED AT %s DUE TO NODE "
			      "FAILURE, SEE SLURMCTLD LOG FOR DETAILS ***",
			      entity, job->node_name, time_str);
			msg_sent = 1;
		} else if (sig == SIG_REQUEUED) {
			error("*** %s ON %s CANCELLED AT %s DUE TO JOB REQUEUE ***",
			      entity, job->node_name, time_str);
			msg_sent = 1;
		} else if (sig == SIG_FAILURE) {
			error("*** %s ON %s FAILED (non-zero exit code or other "
			      "failure mode) ***",
			      entity, job->node_name);
			msg_sent = 1;
		} else if (sig == SIG_UME) {
			error("*** %s ON %s UNCORRECTABLE MEMORY ERROR AT %s ***",
			      entity, job->node_name, time_str);
		} else if ((sig == SIGTERM) || (sig == SIGKILL)) {
			error("*** %s ON %s CANCELLED AT %s ***",
			      entity, job->node_name, time_str);
			msg_sent = 1;
		}
	}
	if ((sig == SIG_TIME_LIMIT) || (sig == SIG_NODE_FAIL) ||
	    (sig == SIG_PREEMPTED)  || (sig == SIG_FAILURE) ||
	    (sig == SIG_REQUEUED)   || (sig == SIG_UME))
		goto done;

	if (sig == SIG_ABORT) {
		sig = SIGKILL;
		job->aborted = true;
	}

	slurm_mutex_lock(&suspend_mutex);
	if (suspended && (sig != SIGKILL)) {
		rc = -1;
		errnum = ESLURMD_STEP_SUSPENDED;
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	}

	if (sig == SIG_DEBUG_WAKE) {
		int i;
		for (i = 0; i < job->node_tasks; i++)
			pdebug_wake_process(job, job->task[i]->pid);
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	}

	if (flag & KILL_JOB_BATCH
	    && job->stepid == SLURM_BATCH_SCRIPT) {
		/* We should only signal the batch script
		 * and nothing else, the job pgid is the
		 * equal to the pid of the batch script.
		 */
		if (kill(job->pgid, sig) < 0) {
			error("%s: failed signal %d container pid"
			      "%u job %u.%u %m",
			      __func__, sig, job->pgid,
			      job->jobid, job->stepid);
			rc = SLURM_ERROR;
			errnum = errno;
			slurm_mutex_unlock(&suspend_mutex);
			goto done;
		}
		rc = SLURM_SUCCESS;
		errnum = 0;
		verbose("%s: sent signal %d to container pid %u job %u.%u",
			__func__, sig, job->pgid,
			job->jobid, job->stepid);
		slurm_mutex_unlock(&suspend_mutex);
		goto done;
	}

	/*
	 * Signal the container
	 */
	if (proctrack_g_signal(job->cont_id, sig) < 0) {
		rc = -1;
		errnum = errno;
		verbose("Error sending signal %d to %u.%u: %m",
			sig, job->jobid, job->stepid);
	} else {
		verbose("Sent signal %d to %u.%u",
			sig, job->jobid, job->stepid);
	}
	slurm_mutex_unlock(&suspend_mutex);

done:
	/* Send the return code and errnum */
	safe_write(fd, &rc, sizeof(int));
	safe_write(fd, &errnum, sizeof(int));
	return SLURM_SUCCESS;
rwfail:
	return SLURM_FAILURE;
}
Esempio n. 28
0
/* Write some buf1 data to pty, processing IACs.
 * Update wridx1 and size1. Return < 0 on error.
 * Buggy if IAC is present but incomplete: skips them.
 */
static ssize_t
safe_write_to_pty_decode_iac(struct tsession *ts)
{
	unsigned wr;
	ssize_t rc;
	unsigned char *buf;
	unsigned char *found;

	buf = TS_BUF1(ts) + ts->wridx1;
	wr = MIN(BUFSIZE - ts->wridx1, ts->size1);
	/* wr is at least 1 here */

	if (ts->buffered_IAC_for_pty) {
		/* Last time we stopped on a "dangling" IAC byte.
		 * We removed it from the buffer back then.
		 * Now pretend it's still there, and jump to IAC processing.
		 */
		ts->buffered_IAC_for_pty = 0;
		wr++;
		ts->size1++;
		buf--; /* Yes, this can point before the buffer. It's ok */
		ts->wridx1--;
		goto handle_iac;
	}

	found = memchr(buf, IAC, wr);
	if (found != buf) {
		/* There is a "prefix" of non-IAC chars.
		 * Write only them, and return.
		 */
		if (found)
			wr = found - buf;

		/* We map \r\n ==> \r for pragmatic reasons:
		 * many client implementations send \r\n when
		 * the user hits the CarriageReturn key.
		 * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
		 */
		rc = wr;
		found = memchr(buf, '\r', wr);
		if (found)
			rc = found - buf + 1;
		rc = safe_write(ts->ptyfd, buf, rc);
		if (rc <= 0)
			return rc;
		if (rc < wr /* don't look past available data */
		 && buf[rc-1] == '\r' /* need this: imagine that write was _short_ */
		 && (buf[rc] == '\n' || buf[rc] == '\0')
		) {
			rc++;
		}
		goto update_and_return;
	}

	/* buf starts with IAC char. Process that sequence.
	 * Example: we get this from our own (bbox) telnet client:
	 * read(5, "\377\374\1""\377\373\37""\377\372\37\0\262\0@\377\360""\377\375\1""\377\375\3"):
	 * IAC WONT ECHO, IAC WILL NAWS, IAC SB NAWS <cols> <rows> IAC SE, IAC DO SGA
	 * Another example (telnet-0.17 from old-netkit):
	 * read(4, "\377\375\3""\377\373\30""\377\373\37""\377\373 ""\377\373!""\377\373\"""\377\373'"
	 * "\377\375\5""\377\373#""\377\374\1""\377\372\37\0\257\0I\377\360""\377\375\1"):
	 * IAC DO SGA, IAC WILL TTYPE, IAC WILL NAWS, IAC WILL TSPEED, IAC WILL LFLOW, IAC WILL LINEMODE, IAC WILL NEW_ENVIRON,
	 * IAC DO STATUS, IAC WILL XDISPLOC, IAC WONT ECHO, IAC SB NAWS <cols> <rows> IAC SE, IAC DO ECHO
	 */
	if (wr <= 1) {
		/* Only the single IAC byte is in the buffer, eat it
		 * and set a flag "process the rest of the sequence
		 * next time we are here".
		 */
		//bb_error_msg("dangling IAC!");
		ts->buffered_IAC_for_pty = 1;
		rc = 1;
		goto update_and_return;
	}

 handle_iac:
	/* 2-byte commands (240..250 and 255):
	 * IAC IAC (255) Literal 255. Supported.
	 * IAC SE  (240) End of subnegotiation. Treated as NOP.
	 * IAC NOP (241) NOP. Supported.
	 * IAC BRK (243) Break. Like serial line break. TODO via tcsendbreak()?
	 * IAC AYT (246) Are you there. Send back evidence that AYT was seen. TODO (send NOP back)?
	 *  These don't look useful:
	 * IAC DM  (242) Data mark. What is this?
	 * IAC IP  (244) Suspend, interrupt or abort the process. (Ancient cousin of ^C).
	 * IAC AO  (245) Abort output. "You can continue running, but do not send me the output".
	 * IAC EC  (247) Erase character. The receiver should delete the last received char.
	 * IAC EL  (248) Erase line. The receiver should delete everything up tp last newline.
	 * IAC GA  (249) Go ahead. For half-duplex lines: "now you talk".
	 *  Implemented only as part of NAWS:
	 * IAC SB  (250) Subnegotiation of an option follows.
	 */
	if (buf[1] == IAC) {
		/* Literal 255 (emacs M-DEL) */
		//bb_error_msg("255!");
		rc = safe_write(ts->ptyfd, &buf[1], 1);
		/*
		 * If we went through buffered_IAC_for_pty==1 path,
		 * bailing out on error like below messes up the buffer.
		 * EAGAIN is highly unlikely here, other errors will be
		 * repeated on next write, let's just skip error check.
		 */
#if 0
		if (rc <= 0)
			return rc;
#endif
		rc = 2;
		goto update_and_return;
	}
	if (buf[1] >= 240 && buf[1] <= 249) {
		/* NOP (241). Ignore (putty keepalive, etc) */
		/* All other 2-byte commands also treated as NOPs here */
		rc = 2;
		goto update_and_return;
	}

	if (wr <= 2) {
/* BUG: only 2 bytes of the IAC is in the buffer, we just eat them.
 * This is not a practical problem since >2 byte IACs are seen only
 * in initial negotiation, when buffer is empty
 */
		rc = 2;
		goto update_and_return;
	}

	if (buf[1] == SB) {
		if (buf[2] == TELOPT_NAWS) {
			/* IAC SB, TELOPT_NAWS, 4-byte, IAC SE */
			struct winsize ws;
			if (wr <= 6) {
/* BUG: incomplete, can't process */
				rc = wr;
				goto update_and_return;
			}
			memset(&ws, 0, sizeof(ws)); /* pixel sizes are set to 0 */
			ws.ws_col = (buf[3] << 8) | buf[4];
			ws.ws_row = (buf[5] << 8) | buf[6];
			ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
			rc = 7;
			/* trailing IAC SE will be eaten separately, as 2-byte NOP */
			goto update_and_return;
		}
		/* else: other subnegs not supported yet */
	}

	/* Assume it is a 3-byte WILL/WONT/DO/DONT 251..254 command and skip it */
#if DEBUG
	fprintf(stderr, "Ignoring IAC %s,%s\n",
			TELCMD(buf[1]), TELOPT(buf[2]));
#endif
	rc = 3;

 update_and_return:
	ts->wridx1 += rc;
	if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */
		ts->wridx1 = 0;
	ts->size1 -= rc;
	/*
	 * Hack. We cannot process IACs which wrap around buffer's end.
	 * Since properly fixing it requires writing bigger code,
	 * we rely instead on this code making it virtually impossible
	 * to have wrapped IAC (people don't type at 2k/second).
	 * It also allows for bigger reads in common case.
	 */
	if (ts->size1 == 0) { /* very typical */
		//bb_error_msg("zero size1");
		ts->rdidx1 = 0;
		ts->wridx1 = 0;
		return rc;
	}
	wr = ts->wridx1;
	if (wr != 0 && wr < ts->rdidx1) {
		/* Buffer is not wrapped yet.
		 * We can easily move it to the beginning.
		 */
		//bb_error_msg("moved %d", wr);
		memmove(TS_BUF1(ts), TS_BUF1(ts) + wr, ts->size1);
		ts->rdidx1 -= wr;
		ts->wridx1 = 0;
	}
	return rc;
}
Esempio n. 29
0
  static void segv_handler(int sig) {
    static int crashing = 0;
    void* array[64];
    size_t size;

    // So we don't recurse!
    if(crashing) exit(101);

    crashing = 1;

    int fd = STDERR_FILENO;

    if(getenv("RBX_PAUSE_ON_CRASH")) {
      std::cerr << "\n========== CRASH (" << getpid();
      std::cerr << "), pausing for 60 seconds to attach debugger\n";
      sleep(60);
    }

    // If there is a report_path setup..
    if(report_path[0]) {
      fd = open(report_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
      // If we can't open this path, use stderr.
      if(fd == -1) fd = STDERR_FILENO;
    }

    // print out all the frames to stderr
    static const char header[] = 
      "Rubinius Crash Report #rbxcrashreport\n\n"
      "Error: signal ";

    safe_write(fd, header, sizeof(header));
    write_sig(fd, sig);

    safe_write(fd, "\n\n[[Backtrace]]\n");

    // get void*'s for all entries on the stack
    size = backtrace(array, 64);

    backtrace_symbols_fd(array, size, fd);

    // Try to get the output to flush...
    safe_write(fd, "\n[[System Info]]\n");
    safe_write(fd, "sysname: ");
    safe_write(fd, machine_info.sysname);
    safe_write(fd, "\n");
    safe_write(fd, "nodename: ");
    safe_write(fd, machine_info.nodename);
    safe_write(fd, "\n");
    safe_write(fd, "release: ");
    safe_write(fd, machine_info.release);
    safe_write(fd, "\n");
    safe_write(fd, "version: ");
    safe_write(fd, machine_info.version);
    safe_write(fd, "\n");
    safe_write(fd, "machine: ");
    safe_write(fd, machine_info.machine);
    safe_write(fd, "\n");

    // If we didn't write to stderr, then close the file down and
    // write info to stderr about reporting the error.
    if(fd != STDERR_FILENO) {
      close(fd);
      safe_write(2, "\n---------------------------------------------\n");
      safe_write(2, "CRASH: A fatal error has occurred.\n\nBacktrace:\n");
      backtrace_symbols_fd(array, size, 2);
      safe_write(2, "\n\n");
      safe_write(2, "Wrote full error report to: ");
      safe_write(2, report_path);
      safe_write(2, "\nRun 'rbx report' to submit this crash report!\n");
    }

    exit(100);
  }
Esempio n. 30
0
void garden_print(int fd) {
  char line[512];

#ifdef HAVE_PATRICIA
  void cb (prefix_t *prefix, void *data) {
    struct node_pass_through_list *nd =
        (struct node_pass_through_list *)data;
    garden_print_list(fd, nd->ptlist, nd->ptcnt);
  }
#endif

  safe_snprintf(line, sizeof line,
		"static garden (%d/%d):\n",
		_options.num_pass_throughs,
		MAX_PASS_THROUGHS);
  if (!safe_write(fd, line, strlen(line))) /* error */
    ;

#ifdef HAVE_PATRICIA
  if (dhcp->ptree) {
    patricia_process(dhcp->ptree, cb);
  } else
#endif
    garden_print_list(fd,
		      _options.pass_throughs,
		      _options.num_pass_throughs);

  safe_snprintf(line, sizeof line,
		"dynamic garden (%d/%d):\n",
		dhcp->num_pass_throughs,
		MAX_PASS_THROUGHS);
  if (!safe_write(fd, line, strlen(line))) /* error */
    ;

#ifdef HAVE_PATRICIA
  if (dhcp->ptree_dyn) {
    patricia_process(dhcp->ptree_dyn, cb);
  } else
#endif
    garden_print_list(fd,
		      dhcp->pass_throughs,
		      dhcp->num_pass_throughs);

#ifdef ENABLE_AUTHEDALLOWED
  safe_snprintf(line, sizeof line,
		"authed garden (%d/%d):\n",
		_options.num_authed_pass_throughs,
		MAX_PASS_THROUGHS);
  if (!safe_write(fd, line, strlen(line))) /* error */;

#ifdef HAVE_PATRICIA
  if (dhcp->ptree_authed) {
    patricia_process(dhcp->ptree_authed, cb);
  } else
#endif
    garden_print_list(fd,
		      _options.authed_pass_throughs,
		      _options.num_authed_pass_throughs);
#endif

#ifdef ENABLE_SESSGARDEN
  chilli_appconn_run(garden_print_appconn, &fd);
#endif
}