0

I'm implementing a http server in C. I have a custom function for writing headers. When I call it, it doesn't do anything. I have placed an arbitrary printf inside the function, to make sure that it's called, and it doesn't produce output too. Program compiles with success, and works normally as intended, aside from this issue. I can connect to server, which results in empty response due to this problem. I can easily use fprintf instead, but I want to understand the problem. The function is declared as follows:

void write_response_ln(FILE *fp, char *format, ...)
{
    va_list args;
    printf("dsgsfdg");
    strcat(format, "\r\n");
    va_start(args, format);
    vfprintf(fp, format, args);
    va_end(args);
}

It is located in it's own file, apart from the file in which the caller is. Even though it is called 4 times, client processes report empty response. Why does this happen? BTW I'm using gcc 4.7 on linux to compile this.


Here is the caller function:
static pid_t handle_connection(size_t bfrsz, int fd_connect, pid_t kid_pid)
{
    int     c;
    char    *headers    = malloc(bfrsz);
    FILE    *res        = fdopen(fd_connect, "a+");

    kid_pid = getpid();

    bzero(headers, bfrsz);

    fgets(headers, bfrsz, res);

    fprintf(stdout, "REQ: %s\n", headers);
    write_response_ln(res, "HTTP 200 OK");
    write_response_ln(res, "Content-Type:text/html");
    write_response_ln(res, "");
    write_response_ln(res, "I don't have a parser yet.");

    fclose(res);
    // Commit suicide.
    printf("Transaction: Complete: Kill: [%d]\n", kid_pid);
    sleep(1);
    kill(kid_pid, SIGINT);
    free(headers);
    return kid_pid;
}

And a go with the gdb gave me this:

(gdb) break write_response_ln
Breakpoint 1 at 0x400f80: file headers.c, line 8.
(gdb) run
Starting program: /home/goktug/code/server/src/server 

Program received signal SIGSEGV, Segmentation fault.
0x0000003491239f24 in ____strtoll_l_internal () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.15-58.fc17.x86_64

As a little note, I haven't done the getopt part yet, so the program segfaults when called without arguments.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • How are you calling this function? Sounds like you're using it as a cURL callback... –  Jan 01 '13 at 23:51
  • Maybe buffer issues? Try printing a line break or `fflush(stdout);` – pmg Jan 01 '13 at 23:51
  • Sounds similar to [this](http://stackoverflow.com/a/1716621/981380). pmg's solution above should work for you. – dinesh Jan 01 '13 at 23:53
  • If you run your program in the debugger and set a breakpoint in the function, does it catch it? – Barmar Jan 01 '13 at 23:58
  • @H2CO3 nope, I'm not using curl, currently this is a basic forking server, which writes hardcoded 4 lines. @pmg, @dinesh, I tried to fflush both `stdout` and `fp`, no effect. @Barmar, I know nothing about gdb, how should I do that? –  Jan 02 '13 at 00:00
  • Show us the code that calls this... – Mats Petersson Jan 02 '13 at 00:05
  • @MatsPetersson just edited. –  Jan 02 '13 at 00:10
  • Also you cannot switch between writing and reading from a `FILE` without a file positioning statement separating the read/write (you can try `fseek(res, 0, SEEK_CUR);`). – pmg Jan 02 '13 at 00:18

1 Answers1

3

You are using string literals, which are constants:

write_response_ln(res, "HTTP 200 OK");

and you are trying to modify them:

strcat(format, "\r\n");

Instead, use a temporary non-constant buffer and copy the format first.

perreal
  • 94,503
  • 21
  • 155
  • 181
  • 1
    +1: they are constant (I prefer to cal them unmodifiable to avoid confusions) but not `const` :-) – pmg Jan 02 '13 at 00:16
  • It's not declared to be constant in `write_respons_ln`, instead, it is a `char *`. Shouldn't that be mutable? –  Jan 02 '13 at 00:18
  • No, it is about the type of the parameter you are passing into the function, not about the type of function arguments. You can compile with `-Wall` flags and should get a warning. – perreal Jan 02 '13 at 00:20
  • It will crash when you try to strcat tho' - although it seems to crash in strtoll, which isn't part of the code you have posted, so don't know what's happening there. – Mats Petersson Jan 02 '13 at 00:22
  • That is because I use argv[1] directly as a function argument, I havent done getopt yet. –  Jan 02 '13 at 00:28