a problem about ffi function call in openresty - luajit

I have some code writen in c, and I wraped these code by lua ffi. When I call my lua file directly by luajit,It works fine.but when I call it from openresty, openresty got an error log: exit on signal 11
nginx version: openresty/1.15.8.1
operating system: debian 9
system luajit: LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall.
openresty luajit: LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall.
I write a test file to show the different result of two platform
-- filename: gateway/test.lua
local ffi = require "ffi"
ffi.cdef [=[
typedef struct _TrigxNode {
int val;
struct _TrigxNode *char_nodes[64];
struct _TrigxNode *rgx_next;
int rgx_raw_len;
void *re;
char *rgx;
} TrigxNode;
TrigxNode *create_trigx_node();
void trigx_insert(TrigxNode *root, const char *word, int len_word, int val);
int trigx_search(TrigxNode *root, const char *word, int len_word);
void trigx_free(TrigxNode *root);
]=];
local C = ffi.load("trigx_tree")
local node = C.create_trigx_node()
C.trigx_insert(node, '/menu/', 6, 10)
local result = C.trigx_search(node, '/menu/', 6)
if ngx ~= nil then
-- test in openresty
ngx.say("result: " .. result)
else
-- test in luajit
print("result: " .. result)
end
return
http {
init_worker_by_lua_block {
local uuid = require 'resty.jit-uuid'
uuid.seed()
local verbose = false
if verbose then
local dump = require "jit.dump"
dump.on(nil, "./jit.log")
else
local v = require "jit.v"
v.on("./jit.log")
end
require "resty.core"
}
server {
listen 9090;
location / {
content_by_lua_file "gateway/test.lua";
}
location /login {
default_type 'application/json';
content_by_lua_file 'gateway/login.lua';
}
location /wechat-callback {
content_by_lua_file 'gateway/wechat_identify.lua';
}
}
}
when i call the ffi function directly by luajit, luajit -i gateway/test.lua,I can see the right result are printed
but when i try to call test.lua in nginx worker by curl 'localhost:9090/abc',error occured
two pictures show the detail of result

I use calloc rather malloc in source file then problem solved.but still can't find out why this can work in luajit

Related

Is there the ways to forward output from XCode to Processing?

I'm trying out to forward output stream from XCode (v12.4) to Processing (https://processing.org/).
My goal is: To draw a simple object in Processing according to my XCode project data.
I need to see value of my variable in the Processing.
int main(int argc, const char * argv[]) {
// insert code here...
for (int i=0; i<10; i++)
std::cout << "How to send value of i to the Processing!\n";
return 0;
}
Finally I found the way. Hope it help someone. Share it.
Xcode app ->(127.0.0.1:UDP)-> Processing sketch
Source Links:
Sending string over UDP in C++
https://discourse.processing.org/t/receive-udp-packets/19832
Xcode app (C++):
int main(int argc, char const *argv[])
{
std::string hostname{"127.0.0.1"};
uint16_t port = 6000;
int sock = ::socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in destination;
destination.sin_family = AF_INET;
destination.sin_port = htons(port);
destination.sin_addr.s_addr = inet_addr(hostname.c_str());
std::string msg = "Hello world!";
for(int i=0; i<5; i++){
long n_bytes = ::sendto(sock, msg.c_str(), msg.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
std::cout << n_bytes << " bytes sent" << std::endl;
}
::close(sock);
return 0;
}
Processing code:
import java.net.*;
import java.io.*;
import java.util.Arrays;
DatagramSocket socket;
DatagramPacket packet;
byte[] buf = new byte[12]; //Set your buffer size as desired
void setup() {
try {
socket = new DatagramSocket(6000); // Set your port here
}
catch (Exception e) {
e.printStackTrace();
println(e.getMessage());
}
}
void draw() {
try {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
//Received as bytes:
println(Arrays.toString(buf));
//If you wish to receive as String:
String received = new String(packet.getData(), 0, packet.getLength());
println(received);
}
catch (IOException e) {
e.printStackTrace();
println(e.getMessage());
}
}
The assumption is you're using c++ in Xcode (and not Objective-C, nor Swift).
Every processing sketch inherits the args property (very similar to main's const char * argv[] in c++ program). You can make use of that to initialise a Processing sketch with options from c++.
You could have something like:
int main(int argc, const char * argv[]) {
system("/path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run 0,1,2,3,4,5,6,7,8,9");
return 0;
}
(This is oversimplified, you'd have your for loop accumulate ints into a string with a separator character, maybe setup variables for paths to processing-java and the processing sketch)
To clarify, processing-java is a command line utility that ships with Processing. (You can find it in inside the Processing.app folder (via show contents), alongside the processing executable and install it via Tools menu inside Processing). It allows you to easily run a sketch from the command line. Alternatively, you can export an application, however if you're prototyping, the processing-java option might be more practical.
In Processing you'd check if the sketch was launched with arguments, and if so, parse those arguments.
void setup(){
if(args != null){
printArray(args);
}
}
You can use split() to split 0,1,2,3,4,5,6,7,8,9 into individual numbers that can be parsed (via int() for example).
If you have more complex data, you can consider formatting your c++ output as JSON, then using parseJSONObject() / parseJSONArray().
(If you don't want to split individual values, you can just use spaces with command line arguments: /path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run 0 1 2 3 4 5 6 7 8 9. If you want to send a JSON formatted string from c++, be aware you may need to escape " (e.g. system("/path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run {\"myCppData\":[0,1,2]}");)
This would work if you need to launch the processing sketch once and initialise with values from your c++ program at startup. Outside of the scope of your question, if you need to continously send values from c++ to Processing, you can look at opening a local socket connection (TCP or UDP) to estabish communication between the two programs. One easy to use protocol is OSC (via UDP). You can use oscpack in raw c++ and oscp5 in Processing. (Optionally, depending on your setup you can consider openFrameworks which (already has oscpack integrated as ofxOsc and ships with send/receive examples): its ofApp is similar Processing's PApplet (e.g. setup()/draw()/mousePressed(), etc.)

Missing header <fluent-bit.h> while compiling C program

I'm trying to compile my C program using library Api of fluent-bit , but the header fluent-bit.h is missing and I don't understand why.
I installed fluent-bit using installation guide
Here is my code I want to test:
#include <fluent-bit.h>
int main()
{
int i;
int n;
char tmp[256];
flb_ctx_t *ctx;
int in_ffd;
int out_ffd;
/* Initialize library */
ctx = flb_create();
if (!ctx) {
exit(EXIT_FAILURE);
}
in_ffd = flb_input(ctx, "lib", NULL);
flb_input_set(ctx, in_ffd, "tag", "test", NULL);
out_ffd = flb_output(ctx, "stdout", NULL);
flb_output_set(ctx, out_ffd, "match", "test", NULL);
/* Start the background worker */
flb_start(ctx);
/* Push some data */
for (i = 0; i < 100; i++) {
n = snprintf(tmp, sizeof(tmp) - 1,
"[%f, {\"key\": \"val %i\"}]",
flb_time_now(), i);
flb_lib_push(ctx, in_ffd, tmp, n);
}
flb_stop(ctx);
/* Release Resources */
flb_destroy(ctx);
return 0;
}
Here the error I got:
hello.c:1:24: fatal error: fluent-bit.h: No such file or directory
#include <fluent-bit.h>
^
compilation terminated.
Problem solved, I didn't install fluent-bit and headers properly.
Here was the problem : the headers were missing, so move on to cd /path/to/downloaded/fluent-bit-x.y.z/includes
Then use
sudo cmake .
sudo make install
You'll get an output saying that the headers had been installed on your system.
To make sure fluent-bit is correctly installed too :
cd ..
sudo cmake .
sudo make install
You can now use the fluent-bit API without problems

JeMalloc does not create memory leak dump

I need help with memory profiling using JeMalloc.
I do the following things:
git clone https://github.com/jemalloc/jemalloc
cd jemalloc
./autogen.sh --enable-perf
make dist
make
sudo make install
export MALLOC_CONF=prof_leak:true,lg_prof_sample:0,prof_final:true
export LD_PRELOAD=/usr/local/Cellar/jemalloc/5.1.0/lib/libjemalloc.dylib
Then I run my application:
./some_executed_file
It is 100% that this binary file will use jemalloc
Because when I call
typedef struct {
char *cur;
char *end;
} MallocStatus;
static void GetJemallocStatus(void *mstat_arg, const char *status) {
MallocStatus *mstat = reinterpret_cast<MallocStatus *>(mstat_arg);
size_t status_len = status ? strlen(status) : 0;
size_t buf_size = (size_t)(mstat->end - mstat->cur);
if (!status_len || status_len > buf_size) {
return;
}
snprintf(mstat->cur, buf_size, "%s", status);
mstat->cur += status_len;
}
MallocStatus mstat;
const unsigned int kMallocStatusLen = 1000000;
std::unique_ptr<char[]> buf{new char[kMallocStatusLen + 1]};
mstat.cur = buf.get();
mstat.end = buf.get() + kMallocStatusLen;
je_malloc_stats_print(GetJemallocStatus, &mstat, "");
stats->append(buf.get());
I see JeMalloc statistics.
Regarding to
https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Leak-Checking
I do everything correct - but I still don't see jeprof dump file do analyze memory leaks.
Thanks in advance.
Try adding prof:true,prof_active:true to your MALLOC_CONF, and using --enable-prof flag instead of --enable-perf.

Ruby Gems C extension example not working

I am trying to follow this tutorial on building c extension in ruby gems http://guides.rubygems.org/gems-with-extensions/.
I have the following files:
ext/my_malloc/extconf.rb
require "mkmf"
abort "missing malloc()" unless have_func "malloc"
abort "missing free()" unless have_func "free"
create_makefile "my_malloc/my_malloc"
ext/my_malloc/my_malloc.c
#include <ruby.h>
struct my_malloc {
size_t size;
void *ptr;
};
static void
my_malloc_free(void *p) {
struct my_malloc *ptr = p;
if (ptr->size > 0)
free(ptr->ptr);
}
static VALUE
my_malloc_alloc(VALUE klass) {
VALUE obj;
struct my_malloc *ptr;
obj = Data_Make_Struct(klass, struct my_malloc, NULL, my_malloc_free, ptr);
ptr->size = 0;
ptr->ptr = NULL;
return obj;
}
static VALUE
my_malloc_init(VALUE self, VALUE size) {
struct my_malloc *ptr;
size_t requested = NUM2SIZET(size);
if (0 == requested)
rb_raise(rb_eArgError, "unable to allocate 0 bytes");
Data_Get_Struct(self, struct my_malloc, ptr);
ptr->ptr = malloc(requested);
if (NULL == ptr->ptr)
rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested);
ptr->size = requested;
return self;
}
static VALUE
my_malloc_release(VALUE self) {
struct my_malloc *ptr;
Data_Get_Struct(self, struct my_malloc, ptr);
if (0 == ptr->size)
return self;
ptr->size = 0;
free(ptr->ptr);
return self;
}
void
Init_my_malloc(void) {
VALUE cMyMalloc;
cMyMalloc = rb_const_get(rb_cObject, rb_intern("MyMalloc"));
rb_define_alloc_func(cMyMalloc, my_malloc_alloc);
rb_define_method(cMyMalloc, "initialize", my_malloc_init, 1);
rb_define_method(cMyMalloc, "free", my_malloc_release, 0);
}
I do the following to build the extension:
$ cd ext/my_malloc
$ ruby extconf.rb
checking for malloc()... yes
checking for free()... yes
creating Makefile
$ make
compiling my_malloc.c
linking shared-object my_malloc.bundle
$ cd ../..
$ ruby -Ilib:ext -r my_malloc -e "p MyMalloc.new(5).free"
However, I get the following error on the last command:
/Users/Daniel/.rbenv/versions/2.1.6/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- my_malloc (LoadError)
from
/Users/Daniel/.rbenv/versions/2.1.6/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
Note, I'm using rbenv, I've tried running rbenv rehash and I'm running version 2.1.6.
The correct shell command is:
ruby -Iext/my_malloc -r my_malloc -e "p MyMalloc.new(5).free"
The code also has some other mistakes. Correct
rb_raise(rb_eNoMemError, "unable to allocate %ld bytes", requested);
to
rb_raise(rb_eNoMemError, "unable to allocate %" PRIuSIZE " bytes", requested);
since requested has type size_t and not long (PRIuSIZE is non-standard and defined in "ruby/ruby.h"). And
cMyMalloc = rb_const_get(rb_cObject, rb_intern("MyMalloc"));
to
cMyMalloc = rb_define_class("MyMalloc", rb_cObject);
to actually define the MyMalloc class.

Crazy idea? Program itself tells GDB to watch variable for changes

Why would I need this?
The location of a datum keeps changing because input data varies too much, so other than printing it, sleeping for 30 seconds so I can manually enter it into GDB, then continuing the program, it might be useful to just let the program tell GDB where to watch.
But is such a thing possible?
You can get close; assuming for simplicity C/C++ language
Define a function that returns a reference to your datum to track:
// debug.h
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
You can then subsequently just
(gdb) display GetDatumForDebug()
or even
(gdb) display GetDatumForDebug()->s
I assume it will be possible to use the result of GetDatumForDebug() in your debug watches, I'm not sure what you do/how you do that :)
Here is a working example, crammed in a single source (test.cpp) for speed: compile with g++ -g test.cpp -o test:
static bool s_initialized = false;
struct mydatastruct { const char* s; };
static mydatastruct& some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
{
static mydatastruct s_instance = { "hello world" };
s_initialized = true;
return s_instance;
}
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
int main()
{
// force initialize for demo purpose:
some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return 42;
}
Automate gdb commands
Append the following to .gdbinit in your working directory:
break main
run
call some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
display GetDatumForDebug()? GetDatumForDebug()->s : ""
This will automatically execute these commands on launching gdb in that directory

Resources