I'm developing a FastCGI application using Apache, mod_fastcgi and the fcgapp.h API. Everything works so far, but I'm failing to detect aborted connections. We need to control them, because we are sometimes doing expensive operations which have to be aborted when the user aborts the request.
I'm trying to use the SIGPIPE as indicated in the documentation, but it doesn't seem to work.
I have written a reduced test case to show my problem:
#include <iostream>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fstream>
#include "fcgio.h"
using namespace std;
void signal_handler(int signo) {
cerr << "SIGNAL RECEIVED: " << signo << endl;
}
int main(void) {
streambuf * cin_streambuf = cin.rdbuf();
streambuf * cout_streambuf = cout.rdbuf();
streambuf * cerr_streambuf = cerr.rdbuf();
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = signal_handler;
sa.sa_flags = 0;
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
FCGX_Request request;
int socketfd = FCGX_OpenSocket("/home/guillermo/fastcgi/socket", 10);
FCGX_Init();
FCGX_InitRequest(&request, socketfd, 0);
while (FCGX_Accept_r(&request) == 0) {
fcgi_streambuf cin_fcgi_streambuf(request.in);
fcgi_streambuf cout_fcgi_streambuf(request.out);
fcgi_streambuf cerr_fcgi_streambuf(request.err);
cin.rdbuf(&cin_fcgi_streambuf);
cout.rdbuf(&cout_fcgi_streambuf);
cerr.rdbuf(&cerr_fcgi_streambuf);
sleep(5);
cout << "Content-type: text/html\r\n"
<< "\r\n"
<< "<html>\n"
<< " <head>\n"
<< " <title>Hello, World!</title>\n"
<< " </head>\n"
<< " <body>\n"
<< " <h1>Hello!</h1>\n"
<< " </body>\n"
<< "</html>\n";
cerr << "All right" << endl;
}
cin.rdbuf(cin_streambuf);
cout.rdbuf(cout_streambuf);
cerr.rdbuf(cerr_streambuf);
return 0;
}
I have tried with these two different configurations for mod_fastcgi:
FastCGIExternalServer $file -socket $socket
FastCGIServer $file -socket $socket
No matter if I abort the connection or not, I always get "All right" in the Apache error log after 5 seconds. I have tested it with curl (Ctrl-C) and from different browsers (stop button), as well as with XMLHttpRequest.abort from Javascript (which is the real-world scenario).
This is my system configuration:
Linux Debian 3.2.46-1 x86_64
Apache2 (2.2.22-13)
mod_fastcgi (2.4.1-SNAP-0910052249)
Related
I'm making a calculator using the command line and am using a stack to push the values of the arguments (digits of the calculator and operators), but I keep getting an invalid conversion from 'char*' to 'std::stack""value_type' and "no matching function for call to 'push(char*&)' error. Any ideas on what im doing wrong?
My code:
#include <iostream>
#include <cmath>
#include <stack>
int main(int argc,char* argv[])
{
std::stack<int> numbers;
// std::stack<char> operators;
for(int i=1;i<argc;++i)
{
numbers.push(argv[i]);
//operators.push(argv[i+1]);
}
while(!numbers.empty())
{
std::cout << numbers.top() << std::endl;
numbers.pop();
// std::cout << operators.top() << std::endl;
// operators.pop();
}
return 0;
I've tried using & and * and $ to try to call the values but I just don't think I'm getting something.
Why the interpreter complains that library named "math" does not exist?
As far as I know, this library is loaded when invoking luaL_newstate on Lua-5.3.5.
#include "lua.hpp"
#include <iostream>
#include <assert.h>
#include <fstream>
int main()
{
struct lua_State *L = luaL_newstate();
int ret;
std::string fileName("co.lua");
if(fileName.empty())
{
std::cout << "the filename is empty" << std::endl;
return -1;
}
std::ifstream fileScript(fileName, fileScript.in|std::ios::ate);
if(!fileScript.is_open())
{
std::cout << "open file failed" << std::endl;
return -2;
}
size_t size = fileScript.tellg();
if(size <= 0)
{
std::cout << "file has no valid content" << std::endl;
return -3;
}
std::string textCont(size, '\0');
fileScript.seekg(0);
fileScript.read(&textCont[0], size);
if((ret=luaL_loadbuffer(L, textCont.data(), textCont.length(), "co.lua")) == LUA_OK)
{
if((ret=lua_pcall(L, 0, LUA_MULTRET, 0)) != LUA_OK)
{
std::cout << "error in invoking lua_pcall():" << ret << std::endl;
if(lua_isstring(L, -1))
{
const char *errMsg = lua_tostring(L, -1);
lua_pop(L, 1);
std::cout << "script run encounter err:" << errMsg << std::endl;
}
}
}
}
Here is the code snippet(it's very simple) for the file named "co.lua":
a = 1;
b=2;
a=a+1;
math.sin(a)
Here is the error message in the console:
error in invoking lua_pcall():2
script run encounter err:[string "co.lua"]:29: attempt to index a nil value (global 'math')
The documentation states that you need to call luaL_openlibs or luaL_requiref which does not seem to be the case with your posted program.
To have access to these libraries, the C host program should call the luaL_openlibs function, which opens all standard libraries.
Alternatively (emphasis mine):
Alternatively, the host program can open them individually by using luaL_requiref to call:
luaopen_base (for the basic library)
luaopen_package (for the package library)
luaopen_coroutine (for the coroutine library)
luaopen_string (for the string library)
luaopen_utf8 (for the UTF8 library)
luaopen_table (for the table library)
luaopen_math (for the mathematical library)
luaopen_io (for the I/O library)
luaopen_os (for the operating system library)
luaopen_debug (for the debug library).
These functions are declared in lualib.h.
So change your program's first few lines to something like below.
You also need to compare the return value from luaL_newstate with NULL and handle that error condition.
int main()
{
struct lua_State *L = luaL_newstate();
if( L == NULL ) {
puts( "Lua failed to initialize." );
exit(1);
}
luaL_openlibs( L );
// etc
I am new to libqmi and wanted to start by just opening a new device. But the callback function is never getting called and therefore no device object returned.
I running the code on Ubuntu 64 Bit.
On this website: https://developer.gnome.org/gio/stable/GAsyncResult.html
I found how this should be handled and programmed it that way, but it still doesn't work.
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
using namespace std;
void device_create_start(const char* device_file);
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
cout << "Start\n";
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
GCancellable* cancellable = g_cancellable_new();
GAsyncReadyCallback callback = device_create_stop;
gpointer user_data = NULL;
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, cancellable, callback, user_data);
cout << "INFO: qmi_device_new started!\n";
cout << "INFO: Waiting!\n";
usleep(10000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
cout << "INFO: canceling!\n";
g_cancellable_cancel(cancellable);
cout << "INFO: Waiting again!\n";
usleep(100000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device file!\n";
}
}
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
cout << "INFO: device_create_stop\n";
something = 2;
cout << "INFO: qmi_device_new_finish starting\n";
GError *error;
QmiDevice* device = qmi_device_new_finish(res, &error);
cout << "INFO: qmi_device_new_finish started\n";
if(device == NULL)
{
cout << "ERROR: Could not create device!\n";
}
else
{
cout << "INFO: Device created!\n";
//device_open(device);
}
}
When I run this code the output is:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
INFO: Waiting!
INFO: Is cancelled?: 0
INFO: canceling!
INFO: Waiting again!
INFO: Is cancelled?: 1
DEBUG: Something: 1
Stop
The code in the callback function is never called.
Update 1
I simplified the code and changed some things that I oversaw on the gnome reference site, like a static callback function. But this doesn't work either
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
#include <glib/gprintf.h>
using namespace std;
void device_create_start(const char* device_file);
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
g_printf ("Start\n");
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
while(true)
{
;
}
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, NULL, device_create_stop, NULL);
cout << "INFO: qmi_device_new started!\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device!\n";
}
}
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
g_printf ("Hurray!\n");
something = 2;
}
The new output:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
DEBUG: Something: 1
Does anyone has a clue why this is not working?
As Philip said (hey Philip!), you're missing the main loop. The qmi_device_new() function is an method that finishes asynchronously, and once finished, the result of the operation is provided in the callback function you provide. In order for the asynchronous function to even do something, you need to have a GMainLoop running for as long as your program logic runs.
I have created a simple CNN model which I froze into tf_model.pb file and I have tried loading it using open cv dnn.readNetFromTesnorflow(model_path) method inside Jupyter Notebook and it works perfectly. The problem is when I try to load it inside Visual Studio 2017, for some reason it does not load correctly.
Here is my code:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
using namespace cv;
using namespace cv::dnn;
int main(int argc, char** argv) {
class CharNet {
private:
Net network;
string output_layer;
public:
CharNet(string path) {
try {
cout << "Path: "<< path << endl;
network = readNetFromTensorflow(path);
vector<String> network_layers = network.getLayerNames();
cout << "There are "<<network_layers.size()<< " layers" << endl;
for (int i = 0; i < network_layers.size(); i++) {
cout << network_layers[i] << endl;
if ( network_layers[i].find("Softmax") != std::string::npos ) {
cout << "Output Layer: "<< network_layers[i] << endl;
output_layer = network_layers[i];
break;
}
}
}
catch (cv::Exception& e) {
cerr << "Exception: " << e.what() << endl;
if (network.empty()) {
cerr << "Can't load the model" << endl;
}
}
}
};
string model = "C:/Users/stefan_cepa995/source/repos/OpenCV_Test/OpenCV_Test/tf_model.pb";
CharNet* obj = new CharNet(model);
return 0;
}
Since the model is not loaded correctly I never enter the for loop. Does anyone have any idea whats going on?
i have a question regarding the binding of variables using the otl_stream.
No matter how i bind, using indexed or naming the order/naming does not affect which column is being updated. It seems always sequential.
You can see that in otl_stream the column-names have been switched. However
the postgres DB shows that both inserts yield equal results.
OS:Windows
OTL:4.0
Visual Studio 2013.
Platform: x64
ODBC: PostgreSQL ANSI(x64) 9.03.04.00
Any ideas?
Kind Regards Auke-Dirk
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
// #define OTL_ODBC_UNIX // uncomment this line if UnixODBC is used
#define OTL_ODBC_ALTERNATE_RPC
#if !defined(_WIN32) && !defined(_WIN64)
#define OTL_ODBC
#else
#define OTL_ODBC_POSTGRESQL // required with PG ODBC on Windows
#endif
#include "otlv4_h2\otlv4.h"
int _tmain(int argc, _TCHAR* argv[])
{
otl_connect db;
otl_connect::otl_initialize(); // initialize ODBC environment
try{
db.rlogon("Driver=PostgreSQL ANSI;Server=localhost;Database=Horus;UID=postgres;PWD=12odsc7a");
otl_cursor::direct_exec
(
db,
"drop table test_tab",
otl_exception::disabled // disable OTL exceptions
); // drop table
db.commit();
otl_cursor::direct_exec
(
db,
"create table test_tab(f1 int, f2 int)"
); // create table
db.commit();
otl_stream ostr1(1, // no buffers
"insert into test_tab values(:f1<int>,:f2<int>)",
db
);
ostr1 << 1 << 2;
db.commit();
otl_stream ostr2(1, // no buffers
"insert into test_tab values(:f2<int>,:f1<int>)",
db
);
ostr2 << 1 << 2;
db.commit();
}
catch (otl_exception& p){ // intercept OTL exceptions
cerr << p.msg << endl; // print out error message
cerr << p.stm_text << endl; // print out SQL that caused the error
cerr << p.sqlstate << endl; // print out SQLSTATE message
cerr << p.var_info << endl; // print out the variable that caused the error
}
db.logoff(); // disconnect from ODBC
return 0;
}
I Could not resolve this issue and therefor moved on to soci.
Regards