question about sending data

46 views
Skip to first unread message

Jack Levin

unread,
Apr 27, 2014, 3:15:00 PM4/27/14
to nx...@googlegroups.com
Yaroslav, thanks for developing cool and fast webserver.  I have a question, here is the code snippet from one of the modules:

static nxweb_result benchmark_on_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {
  resp->content_type="text/html";
  resp->content="<p>Hello, world!</p>";
  resp->content_length=sizeof("<p>Hello, world!</p>")-1;
  return NXWEB_OK;
}

I am planning to send binary data (unsigned *char) in my module.  What is the best way to use "resp->content=" to send binary data via http?

Thanks.

-Jack

Yaroslav

unread,
Apr 27, 2014, 3:31:00 PM4/27/14
to nx...@googlegroups.com
Hi Jack,

Just point resp->content to your binary data and that is it.

Make sure you set content_length and content_type correctly.

Use nxb_* functions to allocate memory for your response unless it is constant like in my benchmark example. See here for details: https://groups.google.com/d/msg/nxweb/rfj2KDBQraQ/UR5bEo2QEzkJ

Yaroslav



--
You received this message because you are subscribed to the Google Groups "nxweb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nxweb+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jack Levin

unread,
Apr 27, 2014, 4:02:40 PM4/27/14
to nx...@googlegroups.com
Hello, I did following mods to benchmark module:

FILE *fd;
char buff[528860];
memset(buff,0,sizeof(buff));
fd = fopen("/root/out.jpg", "rb");
fread(buff,1,528860,fd);

resp->content_type="image/jpg";
resp->content=buff;
resp->content_length=528860;

// resp->content="<p>Hello, world!</p>";
// resp->content_length=sizeof("<p>Hello, world!</p>")-1;
return NXWEB_OK;

How would you use nxb_* functions effectively if the binary data is
always different. e.g. produced by another library and given as a
pointer. If depending on http_request, I have a function
return_data, that returns a struct such as ptr to data and size of
ptr, does it make sense to use nxb_ functions in the return_data
function?


Thanks,
-Jack
> You received this message because you are subscribed to a topic in the
> Google Groups "nxweb" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/nxweb/ulT31suQTGU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to

Jack Levin

unread,
Apr 27, 2014, 4:36:40 PM4/27/14
to nx...@googlegroups.com
I made following changes,

static nxweb_result benchmark_on_request(nxweb_http_server_connection*
conn, nxweb_http_request* req, nxweb_http_response* resp) {

FILE *fd;
char buff[528860];
memset(buff,0,sizeof(buff));
fd = fopen("/root/out.jpg", "rb");
fread(buff,1,528860,fd);

//void* ptr1=nxb_alloc_obj(req->nxb, 528860);

nxb_make_room(req->nxb, 528860);
nxb_append_char_fast(req->nxb, *buff);

resp->content_type="image/jpg";
resp->content=(const char*) req->nxb;
resp->content_length=528860;

int result_size;
char* result=nxb_finish_stream(req->nxb, &result_size);

// resp->content="<p>Hello, world!</p>";
// resp->content_length=sizeof("<p>Hello, world!</p>")-1;
return NXWEB_OK;
}


However, benchmarks do work well, there is a some sort of connection abort:

ab -n25000 -c2 http://rdcv8:8055/benchmark-inprocess
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking rdcv8 (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 732 requests completed

Any ideas?

Jack Levin

unread,
Apr 27, 2014, 4:49:03 PM4/27/14
to nx...@googlegroups.com
Made new changes, but still same issue:

FILE *fd;
char* ptr1=nxb_alloc_obj(req->nxb, 528860);
//char buff[528860];
//memset(buff,0,sizeof(buff));
fd = fopen("/root/out.jpg", "rb");
fread(ptr1,1,528860,fd);


nxb_make_room(req->nxb, 528860);
nxb_append_char_fast(req->nxb, *ptr1);

resp->content_type="image/jpg";
resp->content=(const char*) req->nxb;
resp->content_length=528860;

int result_size=528860;
char* result=nxb_finish_stream(req->nxb, &result_size);
close(fd);
// resp->content="<p>Hello, world!</p>";
// resp->content_length=sizeof("<p>Hello, world!</p>")-1;
return NXWEB_OK;

However, process crashes, after 900+ queries:

rt_sigaction(SIGTERM, {0x7fd04856f000, [TERM], SA_RESTORER|SA_RESTART,
0x7fd047bc7920}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {0x7fd04856f000, [INT], SA_RESTORER|SA_RESTART,
0x7fd047bc7920}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGUSR1, {0x7fd04856efc0, [USR1], SA_RESTORER|SA_RESTART,
0x7fd047bc7920}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x7fd04856efc0, [HUP], SA_RESTORER|SA_RESTART,
0x7fd047bc7920}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGALRM, {0x7fd04856eb00, [ALRM], SA_RESTORER|SA_RESTART,
0x7fd047bc7920}, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [HUP INT QUIT USR1 TERM], NULL, 8) = 0
futex(0x7fd0479869d0, FUTEX_WAIT, 24782, NULL2014-04-27 13:48:20 1
[24781:0x7fd0235fe700]: accept() failed 24
<unfinished ...>
+++ killed by SIGSEGV +++
Segmentation fault

Memory leak?

-Jack

Yaroslav

unread,
Apr 27, 2014, 5:02:03 PM4/27/14
to nx...@googlegroups.com
Looks like C is not your native language ;)

  FILE *fd;
  char* ptr1=nxb_alloc_obj(req->nxb, 528860); -- this is OK

  //char buff[528860]; -- this was NOT OK
  //memset(buff,0,sizeof(buff)); -- you cannot use stack memory after returning from function in C

  fd = fopen("/root/out.jpg", "rb");
  fread(ptr1,1,528860,fd);

  nxb_make_room(req->nxb, 528860); -- you have already allocated memory from nxb, why are you allocating it again?
  nxb_append_char_fast(req->nxb, *ptr1); -- ??? nxb_append_char_fast() appends single byte to nxb stream

  resp->content_type="image/jpg";
  resp->content=(const char*) req->nxb; -- req->nxb is not what you allocated; use ptr1 here
  resp->content_length=528860;

  int result_size=528860; -- result_size is output parameter, not input
  char* result=nxb_finish_stream(req->nxb, &result_size); -- after calling this result points to first byte of your buffer; result_size equals 1

  close(fd);
  // resp->content="<p>Hello, world!</p>";
  // resp->content_length=sizeof("<p>Hello, world!</p>")-1;
  return NXWEB_OK;

This code should work:

  char* ptr1=nxb_alloc_obj(req->nxb, 528860);
  FILE *fd = fopen("/root/out.jpg", "rb");
  fread(ptr1,1,528860,fd);
  close(fd);
  resp->content_type="image/jpeg"; // not jpg!
  resp->content=(const char*)ptr1;
  resp->content_length=528860;
  return NXWEB_OK;


Jack Levin

unread,
Apr 27, 2014, 8:03:44 PM4/27/14
to nx...@googlegroups.com
Here is my code (changed per your post), still have a problem:


FILE *fd;
char* ptr1=nxb_alloc_obj(req->nxb, 528860);
fd = fopen("/root/out.jpg", "rb");
fread(ptr1,1,528860,fd);

close(fd);

resp->content_type="image/jpeg";
resp->content=(const char*) ptr1;
resp->content_length=528860;

return NXWEB_OK;

Benchmarking rdcv8 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
apr_socket_recv: Connection refused (111)
Total of 977 requests completed

Any ideas?

Jack Levin

unread,
Apr 27, 2014, 8:58:34 PM4/27/14
to nx...@googlegroups.com
Here is gdb output:

2014-04-27 17:57:56 1 [20435:0x7fffe75fe700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7ffff51c0700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7fffe4dfa700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7fffc7fff700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7fffc6bfd700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7fffe61fc700]: accept() failed 24
2014-04-27 17:57:56 1 [20435:0x7fffe57fb700]: accept() failed 24

Program received signal SIGSEGV, Segmentation fault.

Jack Levin

unread,
Apr 27, 2014, 8:59:20 PM4/27/14
to nx...@googlegroups.com
Sorry for the spam, here is the trace:

#0 0x00007ffff7239684 in fread () from /lib64/libc.so.6
#1 0x000000000040152d in hello_on_request (conn=<value optimized
out>, req=<value optimized out>, resp=0x7fffbc004a58) at
modules/hello.c:28
#2 0x00007ffff7badee3 in invoke_request_handler (sub=0x7fffbc004e08,
pub=<value optimized out>, data=<value optimized out>) at
http_server.c:416
#3 nxweb_http_server_connection_events_sub_on_message
(sub=0x7fffbc004e08, pub=<value optimized out>, data=<value optimized
out>) at http_server.c:501
#4 0x00007ffff7bbb0cf in nxe_process_loop (loop=0x7fffbc0008c0) at
nx_event.c:163
#5 0x00007ffff7bbb283 in nxe_run (loop=0x7fffbc0008c0) at nx_event.c:196
#6 0x00007ffff7bac8ef in net_thread_main (ptr=0x7ffff7dd9ee0) at
http_server.c:828
#7 0x00007ffff756c851 in start_thread () from /lib64/libpthread.so.0
#8 0x00007ffff72ba90d in clone () from /lib64/libc.so.6

Jack Levin

unread,
Apr 27, 2014, 9:04:33 PM4/27/14
to nx...@googlegroups.com
Alright! Looks like I resolved it, here is the way to start nxweb not
to hit fds limit ;)

imit -n 128000 && /usr/local/bin/nxweb -d -l nxweb_error_log

-Jack

Jack Levin

unread,
Apr 27, 2014, 9:04:44 PM4/27/14
to nx...@googlegroups.com
ulimit -n 128000 && /usr/local/bin/nxweb -d -l nxweb_error_log

Jack Levin

unread,
Apr 27, 2014, 9:14:02 PM4/27/14
to nx...@googlegroups.com
So, this still maybe a bug, check this out, file descriptors do not
drop off when I stop sending requests:


lr-x------ 1 root root 64 Apr 27 18:08 20097 -> /root/out.jpg
lr-x------ 1 root root 64 Apr 27 18:08 20096 -> /root/out.jpg
lr-x------ 1 root root 64 Apr 27 18:08 20095 -> /root/out.jpg
lr-x------ 1 root root 64 Apr 27 18:08 20094 -> /root/out.jpg
lr-x------ 1 root root 64 Apr 27 18:08 20093 -> /root/out.jpg


18:09:27 38.99.79.21 root@rdcv8:/home/jack/nxweb-3.2.0-dev $ ls -ltr
/proc/10746/fd | wc -l
100038

This causes the same error when I resume httpress test in few minutes.
I assume there should be some sort of "Clean fds" code. If course if
another library is used that is called from the module, it would be
its own responsibility to clear the used file descriptor, but still,
Doing the same test with Nginx/PHP combo does not leak file
descriptors.

-Jack




Jack Levin

unread,
Apr 27, 2014, 11:33:37 PM4/27/14
to nx...@googlegroups.com
Alright, it was a bug in the module code, but its not my fault ;), I
just copy pasted your suggestion. The fds leaking were due to this

close(fd); should be
fclose(fd);

Testing going well so far.

TOTALS: 30 connect, 100000 requests, 100000 success, 0 fail, 30 (30)
real concurrency
TRAFFIC: 528860 avg bytes, 155 avg overhead, 52886000000 bytes,
15500000 overhead
TIMING: 12.767 seconds, 7832 rps, 4046434 kbps, 3.8 ms avg req time

Yaroslav

unread,
Apr 28, 2014, 2:46:02 AM4/28/14
to nx...@googlegroups.com
Glad you have figured it all out!
Reply all
Reply to author
Forward
0 new messages