Example #1
0
static rs_result rs_patch_s_copy(rs_job_t *job)
{
    rs_long_t  where, len;
    rs_stats_t      *stats;

    where = job->param1;
    len = job->param2;
        
    rs_trace("COPY(where=" PRINTF_FORMAT_U64 ", len=" PRINTF_FORMAT_U64 ")", PRINTF_CAST_U64(where), PRINTF_CAST_U64(len));

    if (len < 0) {
        rs_log(RS_LOG_ERR, "invalid length=" PRINTF_FORMAT_U64 " on COPY command", PRINTF_CAST_U64(len));
        return RS_CORRUPT;
    }

    if (where < 0) {
        rs_log(RS_LOG_ERR, "invalid where=" PRINTF_FORMAT_U64 " on COPY command", PRINTF_CAST_U64(where));
        return RS_CORRUPT;
    }

    job->basis_pos = where;
    job->basis_len = len;

    stats = &job->stats;

    stats->copy_cmds++;
    stats->copy_bytes += len;
    stats->copy_cmdbytes += 1 + job->cmd->len_1 + job->cmd->len_2;

    job->statefn = rs_patch_s_copying;
    return RS_RUNNING;
}
Example #2
0
File: exec.c Project: katakk/distcc
/**
 * Analyze and report to the user on a command's exit code.
 *
 * @param command short human-readable description of the command (perhaps
 * argv[0])
 *
 * @returns 0 if the command succeeded; 128+SIGNAL if it stopped on a
 * signal; otherwise the command's exit code.
 **/
int dcc_critique_status(int status,
                        const char *command,
                        const char *input_fname,
                        struct dcc_hostdef *host,
                        int verbose)
{
    int logmode;

    /* verbose mode is only used for executions that the user is likely to
     * particularly need to know about */
    if (verbose)
        logmode = RS_LOG_ERR | RS_LOG_NONAME;
    else
        logmode = RS_LOG_INFO | RS_LOG_NONAME;

    if (input_fname == NULL)
        input_fname = "(null)";

    if (WIFSIGNALED(status)) {
#ifdef HAVE_STRSIGNAL
        rs_log(logmode,
               "%s %s on %s: %s%s",
               command, input_fname, host->hostdef_string,
               strsignal(WTERMSIG(status)),
               WCOREDUMP(status) ? " (core dumped)" : "");
#else
        rs_log(logmode,
               "%s %s on %s terminated by signal %d%s",
               command, input_fname, host->hostdef_string,
               WTERMSIG(status),
               WCOREDUMP(status) ? " (core dumped)" : "");
#endif
        /* Unix convention is to return 128+signal when a subprocess crashes. */
        return 128 + WTERMSIG(status);
    } else if (WEXITSTATUS(status) == 1) {
        /* Normal failure gives exit code 1, so handle that specially */
        rs_log(logmode, "%s %s on %s failed", command, input_fname, host->hostdef_string);
        return WEXITSTATUS(status);
    } else if (WEXITSTATUS(status)) {
        /* This is a tough call; we don't really want to clutter the client's
         * error stream, but if we don't say where the compilation failed then
         * people may find it hard to work things out. */

        rs_log(logmode,
               "%s %s on %s failed with exit code %d",
               command, input_fname, host->hostdef_string, WEXITSTATUS(status));
        return WEXITSTATUS(status);
    } else {
        rs_log(RS_LOG_INFO|RS_LOG_NONAME,
               "%s %s on %s completed ok", command, input_fname, host->hostdef_string);
        return 0;
    }
}
Example #3
0
void rs_sumset_dump(rs_signature_t const *sums)
{
    int i;
    rs_block_sig_t *b;
    char strong_hex[RS_MAX_STRONG_SUM_LENGTH * 3];

    rs_log(RS_LOG_INFO|RS_LOG_NONAME, "sumset info: magic=%#x, block_len=%d, block_num=%d",
           sums->magic, sums->block_len, sums->count);

    for (i = 0; i < sums->count; i++) {
        b = rs_block_sig_ptr(sums, i);
        rs_hexify(strong_hex, b->strong_sum, sums->strong_sum_len);
        rs_log(RS_LOG_INFO|RS_LOG_NONAME, "sum %6d: weak="FMT_WEAKSUM", strong=%s", i, b->weak_sum, strong_hex);
    }
}
Example #4
0
File: clinet.c Project: aosm/distcc
/*
 * Connect to a host given its binary address, with a timeout.
 * 
 * host and port are only here to aid printing debug messages.
 */
static int
dcc_connect_by_addr(struct sockaddr *sa, size_t salen,
                    int *p_fd)
{
    int fd;
    int ret;
    char *s;
    int failed;

    dcc_sockaddr_to_string(sa, salen, &s);

    rs_trace("started connecting to %s", s);

    if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) {
        rs_log_error("failed to create socket: %s", strerror(errno));
        ret = EXIT_CONNECT_FAILED;
        goto out_failed;
    }

    dcc_set_nonblocking(fd);

    /* start the nonblocking connect... */
    do
        failed = connect(fd, sa, salen);
    while (failed == -1 && errno == EINTR);

    if (failed == -1 && errno != EINPROGRESS) {
        rs_log(RS_LOG_ERR|RS_LOG_NONAME,
               "failed to connect to %s: %s", s, strerror(errno));
        ret = EXIT_CONNECT_FAILED;
        goto out_failed;
    }

    if ((ret = dcc_select_for_write(fd, dcc_connect_timeout))) {
        rs_log(RS_LOG_ERR|RS_LOG_NONAME,
               "timeout while connecting to %s", s);
        goto out_failed;
    }

    *p_fd = fd;
    free(s);
    return 0;
    
out_failed:
    free(s);
    return ret;
}
Example #5
0
int
rs_log_stats(rs_stats_t const *stats)
{
    char buf[1000];

    rs_format_stats(stats, buf, sizeof buf - 1);
    rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%s", buf);
    return 0;
}
Example #6
0
File: exec.c Project: katakk/distcc
void dcc_note_execution(struct dcc_hostdef *host, char **argv)
{
    char *astr;

    astr = dcc_argv_tostr(argv);
    rs_log(RS_LOG_INFO|RS_LOG_NONAME, "exec on %s: %s",
           host->hostdef_string, astr);
    free(astr);
}
Example #7
0
static void dcc_note_compiled(const char *input_file, const char *output_file)
{
    const char *input_base, *output_base;

    input_base = dcc_find_basename(input_file);
    output_base = dcc_find_basename(output_file);

    rs_log(RS_LOG_INFO|RS_LOG_NONAME,
           "compile from %s to %s", input_base, output_base);
}
Example #8
0
/**
 * Dump signatures to the log.
 */
void
rs_sumset_dump(rs_signature_t const *sums)
{
        int i;
        char        strong_hex[RS_STRONG_SUM_LEN * 3];
    
        rs_log(RS_LOG_INFO, 
                "sumset info: block_len=%d, file length=%lu, "
                "number of chunks=%d, remainder=%d",
                sums->block_len,
                (unsigned long) sums->flength, sums->count,
                sums->remainder);

        for (i = 0; i < sums->count; i++) {
                rs_hexify(strong_hex, sums->block_sigs[i].strong_sum,
                          sums->strong_sum_len);
                rs_log(RS_LOG_INFO,
                        "sum %6d: weak=%08x, strong=%s",
                        i, sums->block_sigs[i].weak_sum, strong_hex);
        }
}
Example #9
0
static void dcc_log_child_exited(pid_t kid,
                                 int status)
{
    if (WIFSIGNALED(status)) {
        int sig = WTERMSIG(status);
        int severity = sig == SIGTERM ? RS_LOG_INFO : RS_LOG_ERR;

        rs_log(severity, "child %d: signal %d (%s)", (int) kid, sig,
               WCOREDUMP(status) ? "core dumped" : "no core");
    } else if (WIFEXITED(status)) {
        rs_log_info("child %d exited: exit status %d",
                    (int) kid, WEXITSTATUS(status));
    }
}
Example #10
0
int main(const int argc, const char *argv[])
{
    poptContext     opcon;
    rs_result       result;

    opcon = poptGetContext(PROGRAM, argc, argv, opts, 0);
    rdiff_options(opcon);
    result = rdiff_action(opcon);

    if (result != RS_DONE)
        rs_log(RS_LOG_ERR|RS_LOG_NONAME, "%s", rs_strerror(result));

    return result;
}
Example #11
0
/**
 * Prepare to compute a streaming delta.
 */
rs_job_t *rs_delta_begin(rs_signature_t *sig)
{
    rs_job_t *job;

    job = rs_job_new("delta", rs_delta_s_header);
    job->signature = sig;

    RollsumInit(&job->weak_sum);

    if ((job->block_len = sig->block_len) < 0) {
        rs_log(RS_LOG_ERR, "unreasonable block_len %d in signature",
               job->block_len);
        return NULL;
    }

    job->strong_sum_len = sig->strong_sum_len;
    if (job->strong_sum_len < 0  ||  job->strong_sum_len > RS_STRONG_SUM_LEN) {
        rs_log(RS_LOG_ERR, "unreasonable strong_sum_len %d in signature",
               job->strong_sum_len);
        return NULL;
    }

    return job;
}
Example #12
0
void rs_signature_log_stats(rs_signature_t const *sig)
{
#ifndef HASHTABLE_NSTATS
    hashtable_t *t = sig->hashtable;

    rs_log(RS_LOG_INFO|RS_LOG_NONAME,
           "match statistics: signature[%ld searches, %ld (%.3f%%) matches, "
           "%ld (%.3fx) weak sum compares, %ld (%.3f%%) strong sum compares, "
           "%ld (%.3f%%) strong sum calcs]",
           t->find_count,
           t->match_count, 100.0 * (double)t->match_count / t->find_count,
           t->hashcmp_count, (double)t->hashcmp_count / t->find_count,
           t->entrycmp_count, 100.0 * (double)t->entrycmp_count / t->find_count,
           sig->calc_strong_count, 100.0 * (double)sig->calc_strong_count / t->find_count);
#endif
}
Example #13
0
/**
 * Called when trying to copy through literal data.
 */
static rs_result rs_patch_s_literal(rs_job_t *job)
{
    rs_long_t   len = job->param1;
    
    rs_trace("LITERAL(len=" PRINTF_FORMAT_U64 ")", PRINTF_CAST_U64(len));

    if (len < 0) {
        rs_log(RS_LOG_ERR, "invalid length=" PRINTF_FORMAT_U64 " on LITERAL command", PRINTF_CAST_U64(len));
        return RS_CORRUPT;
    }

    job->stats.lit_cmds++;
    job->stats.lit_bytes    += len;
    job->stats.lit_cmdbytes += 1 + job->cmd->len_1;

    rs_tube_copy(job, len);

    job->statefn = rs_patch_s_cmdbyte;
    return RS_RUNNING;
}
Example #14
0
/**
 * Called while we're trying to read the header of the patch.
 */
static rs_result rs_patch_s_header(rs_job_t *job)
{
    int       v;
    rs_result result;

        
    if ((result = rs_suck_n4(job, &v)) != RS_DONE)
        return result;

    if (v != RS_DELTA_MAGIC) {
        rs_log(RS_LOG_ERR,
               "got magic number %#x rather than expected value %#x",
               v, RS_DELTA_MAGIC);
        return RS_BAD_MAGIC;
    } else
        rs_trace("got patch magic %#x", v);


    job->statefn = rs_patch_s_cmdbyte;

    return RS_RUNNING;
}
Example #15
0
/**
 * Default copy implementation that retrieves a part of a stdio file.
 */
rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
{
    int        got;
    FILE       *f = (FILE *) arg;

    if (fseek(f, pos, SEEK_SET)) {
        rs_log(RS_LOG_ERR, "seek failed: %s", strerror(errno));
        return RS_IO_ERROR;
    }

    got = fread(*buf, 1, *len, f);
    if (got == -1) {
        rs_error("read error: %s", strerror(errno));
        return RS_IO_ERROR;
    } else if (got == 0) {
        rs_error("unexpected eof on fd%d", fileno(f));
        return RS_INPUT_ENDED;
    } else {
        *len = got;
        return RS_DONE;
    }
}
Example #16
0
rs_result rs_job_iter(rs_job_t *job, rs_buffers_t *buffers)
{
    rs_result       result;
    rs_long_t       orig_in, orig_out;

    orig_in  = buffers->avail_in;
    orig_out = buffers->avail_out;

    result = rs_job_work(job, buffers);

    if (result == RS_BLOCKED  ||  result == RS_DONE)
        if ((orig_in == buffers->avail_in)  &&  (orig_out == buffers->avail_out)
            && orig_in && orig_out) {
            rs_log(RS_LOG_ERR, "internal error: job made no progress "
                   "[orig_in=" PRINTF_FORMAT_U64 ", orig_out=" PRINTF_FORMAT_U64 ", final_in=" PRINTF_FORMAT_U64 ", final_out=" PRINTF_FORMAT_U64 "]",
                   PRINTF_CAST_U64(orig_in), PRINTF_CAST_U64(orig_out), PRINTF_CAST_U64(buffers->avail_in),
                   PRINTF_CAST_U64(buffers->avail_out));
            return RS_INTERNAL_ERROR;
        }

    return result;
}
Example #17
0
void dcc_exit(int exitcode)
{
    struct rusage self_ru, children_ru;

    if (getrusage(RUSAGE_SELF, &self_ru)) {
        rs_log_warning("getrusage(RUSAGE_SELF) failed: %s", strerror(errno));
        memset(&self_ru, 0, sizeof self_ru);
    }
    if (getrusage(RUSAGE_CHILDREN, &children_ru)) {
        rs_log_warning("getrusage(RUSAGE_CHILDREN) failed: %s", strerror(errno));
        memset(&children_ru, 0, sizeof children_ru);
    }

    /* NB fields must match up for microseconds */
    rs_log(RS_LOG_INFO,
           "exit: code %d; self: %d.%06d user %d.%06d sys; children: %d.%06d user %d.%06d sys",
           exitcode,
           (int) self_ru.ru_utime.tv_sec, (int) self_ru.ru_utime.tv_usec,
           (int) self_ru.ru_stime.tv_sec, (int) self_ru.ru_stime.tv_usec,
           (int) children_ru.ru_utime.tv_sec, (int) children_ru.ru_utime.tv_usec,
           (int) children_ru.ru_stime.tv_sec, (int)  children_ru.ru_stime.tv_usec);

    exit(exitcode);
}
Example #18
0
File: serve.c Project: aosm/distcc
/**
 * Read a request, run the compiler, and send a response.
 **/
static int dcc_run_job(int in_fd,
                       int out_fd)
{
    char **argv;
    int status;
    char *temp_i, *temp_o, *err_fname, *out_fname;
    int ret, compile_ret;
    char *orig_input, *orig_output;
    pid_t cc_pid;
    enum dcc_protover protover;
    enum dcc_compress compr;
    dcc_indirection indirect;
    
    if ((ret = dcc_make_tmpnam("distcc", ".stderr", &err_fname)))
        goto out_cleanup;
    if ((ret = dcc_make_tmpnam("distcc", ".stdout", &out_fname)))
        goto out_cleanup;
    
    dcc_remove_if_exists(err_fname);
    dcc_remove_if_exists(out_fname);

    /* Capture any messages relating to this compilation to the same file as
     * compiler errors so that they can all be sent back to the client. */
    dcc_add_log_to_file(err_fname);

    /* Ignore SIGPIPE; we consistently check error codes and will see the
     * EPIPE.  Note that it is set back to the default behaviour when spawning
     * a child, to handle cases like the assembler dying while its being fed
     * from the compiler */
    dcc_ignore_sigpipe(1);

    /* Allow output to accumulate into big packets. */
    tcp_cork_sock(out_fd, 1);

    if ((ret = dcc_r_request_header(in_fd, &protover))
        || (ret = dcc_r_argv(in_fd, &argv))
        || (ret = dcc_scan_args(argv, &orig_input, &orig_output, &argv)))
        goto out_cleanup;
    
    if (strcmp(argv[0],"--host-info") == 0) {
        if ((ret = dcc_x_result_header(out_fd, protover)) ||
            (ret = dcc_send_host_info(out_fd)))
            dcc_x_token_int(out_fd, "DOTO", 0);
    } else {
        
        rs_trace("output file %s", orig_output);
        
        if ((ret = dcc_input_tmpnam(orig_input, &temp_i)))
            goto out_cleanup;
        if ((ret = dcc_make_tmpnam("distccd", ".o", &temp_o)))
            goto out_cleanup;
        
        compr = (protover == 2) ? DCC_COMPRESS_LZO1X : DCC_COMPRESS_NONE;
        
        if ((ret = dcc_r_token_file(in_fd, "DOTI", temp_i, compr))
            || (ret = dcc_set_input(argv, temp_i))
            || (ret = dcc_set_output(argv, temp_o)))
            goto out_cleanup;
        
        if ((ret = dcc_check_compiler_masq(argv[0])))
            goto out_cleanup;
        
        indirect.in_fd = in_fd;
        indirect.out_fd = out_fd;
        if ((compile_ret = dcc_spawn_child(argv, &cc_pid,
                                           "/dev/null", out_fname, err_fname, &indirect))
            || (compile_ret = dcc_collect_child("cc", cc_pid, &status))) {
            /* We didn't get around to finding a wait status from the actual compiler */
            status = W_EXITCODE(compile_ret, 0);
        }
        
        if ((ret = dcc_x_result_header(out_fd, protover))
            || (ret = dcc_send_system_info(out_fd))
            || (ret = dcc_send_compiler_version(out_fd, argv[0]))
            || (ret = dcc_x_cc_status(out_fd, status))
            || (ret = dcc_x_file(out_fd, err_fname, "SERR", compr, NULL))
            || (ret = dcc_x_file(out_fd, out_fname, "SOUT", compr, NULL))
            || WIFSIGNALED(status)
            || WEXITSTATUS(status)) {
            /* Something went wrong, so send DOTO 0 */
            dcc_x_token_int(out_fd, "DOTO", 0);
        } else {
            ret = dcc_x_file(out_fd, temp_o, "DOTO", compr, NULL);
        }
        
        dcc_critique_status(status, argv[0], orig_input, dcc_hostdef_local, 0);
    }
    tcp_cork_sock(out_fd, 0);

    rs_log(RS_LOG_INFO|RS_LOG_NONAME, "job complete");

    out_cleanup:
    dcc_remove_log_to_file();
    dcc_cleanup_tempfiles();

    return ret;
}
Example #19
0
/*
 * Connect to a host given its binary address, with a timeout.
 *
 * host and port are only here to aid printing debug messages.
 */
int dcc_connect_by_addr(struct sockaddr *sa, size_t salen,
                        int *p_fd)
{
    int fd;
    int ret;
    char *s;
    int failed;
    int connecterr;
    int tries = 3;

    dcc_sockaddr_to_string(sa, salen, &s);
    if (s == NULL) return EXIT_OUT_OF_MEMORY;

    rs_trace("started connecting to %s", s);

    if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) {
        rs_log_error("failed to create socket: %s", strerror(errno));
        ret = EXIT_CONNECT_FAILED;
        goto out_failed;
    }

    dcc_set_nonblocking(fd);

    /* start the nonblocking connect... */
    do
        failed = connect(fd, sa, salen);
    while (failed == -1 &&
           (errno == EINTR ||
            (errno == EAGAIN && tries-- && poll(NULL, 0, 500) == 0)));

   if (failed == -1 && errno != EINPROGRESS) {
       rs_log(RS_LOG_ERR|RS_LOG_NONAME,
              "failed to connect to %s: %s", s, strerror(errno));
       ret = EXIT_CONNECT_FAILED;
       goto out_failed;
   }

    do {
       socklen_t len;

       if ((ret = dcc_select_for_write(fd, dcc_connect_timeout))) {
           rs_log(RS_LOG_ERR|RS_LOG_NONAME,
                  "timeout while connecting to %s", s);
           goto out_failed;
       }

       connecterr = -1;
       len = sizeof(connecterr);
       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) {
               rs_log_error("getsockopt SO_ERROR failed?!");
               ret = EXIT_CONNECT_FAILED;
               goto out_failed;
       }

       /* looping is unlikely, but I believe I needed this in dkftpbench */
       /* fixme: should reduce timeout on each time around this loop */
    } while (connecterr == EINPROGRESS);

    if (connecterr) {
       rs_log(RS_LOG_ERR|RS_LOG_NONAME,
                "nonblocking connect to %s failed: %s", s, strerror(connecterr));
       ret = EXIT_CONNECT_FAILED;
       goto out_failed;
    }

    *p_fd = fd;
    free(s);
    return 0;

out_failed:
    free(s);
    return ret;
}