in one constructor that I am analysing are the methods below:
if (validParOptions.found(optionName))
{
parRunControl_.runPar(argc, argv);
break; //leave loop
}
with
ParRunControl parRunControl_ //- Switch on/off parallel mode.
and
void runPar(int& argc, char**& argv)
{
RunPar = true; //bool RunPar;
if (!Pstream::init(argc, argv))
{
Info<< "Failed to start parallel run" << endl;
Pstream::exit(1);
}
}
and herein
bool Foam::UPstream::init(int& argc, char**& argv) //Spawns slave processes and
{ //initialises inter-communication
FatalErrorIn("UPstream::init(int& argc, char**& argv)")
{
<< "Trying to use the dummy Pstream library." << nl
<< "This dummy library cannot be used in parallel mode"
<< Foam::exit(FatalError);
return false;
}
Within the first if condition the existance of options of commandlinearguments are checked and like the description of the last method init tells a slave process should be spawned
und inter-communication should be initialised. Two quesitons:
I don't see where in method init a process is spawned. Rather I only see a
error message within the method. Am I missing something?
Do Options in commandlinearguments generally spawn slave process?
greetings streight
I'm assuming it's a macro because it seems to have lots of different invocations. However, the error message is staring you right in the face: it won't let you use that code.
Take a look at the other source files:
https://github.com/OpenFOAM/OpenFOAM-2.2.x/blob/95dc52c102041058f0bcfc8b6aab6b41b20dc313/src/Pstream/dummy/UPstream.C
https://github.com/OpenFOAM/OpenFOAM-2.2.x/blob/95dc52c102041058f0bcfc8b6aab6b41b20dc313/src/Pstream/dummy/UOPwrite.C
https://github.com/OpenFOAM/OpenFOAM-2.2.x/blob/95dc52c102041058f0bcfc8b6aab6b41b20dc313/src/Pstream/dummy/UIPread.C
They either have empty definitions or contain notImplemented. The big hint is that they all lie in the dummy directory.
My guess is you're probably pulling from the wrong headers. Take a look at this:
https://github.com/OpenFOAM/OpenFOAM-2.2.x/blob/master/src/Pstream/mpi/UPstream.C
It actually has code:
bool Foam::UPstream::init(int& argc, char**& argv)
{
MPI_Init(&argc, &argv);
int numprocs;
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myProcNo_);
/* SNIP */
return true;
}
Related
I'am developping a C++ project on an ESP32.
I'd like to use esp_console + argtable3 (C libraries) in it.
I'm trying to use argtable3 in my members functions.
To do so, I'm creating callback functions to my members functions with a global pointer.
I'm sure my class is going to be instanced only once so I assume it's ok to create callback functions.
The problem is that argtable isn't giving me back the parameters entered by the user.
It checks for them successfully (number of args and their type) but the data it gives me back is random.
I've tested my code outside of members functions and it works well. But I want to use it inside members functions to access other parts of my object.
Here is my code :
// Pointer for my callback functions
MyClass * _callback;
struct arg_int *argInt;
struct arg_end *endPage;
// My callback function (GLOBAL)
int _setInt(int argc, char *argv[])
{
return _callback->setInt(argc, argv);
}
// Tab of struct for argtable lib (GLOBAL)
void *setInt_argtable[] =
{
argInt = arg_int1(NULL, NULL, "<0-12>", "Integer argument"),
endInt = arg_end(10)
};
// Function I'm calling back
int MyClass::setInt(int argc, char *argv[])
{
int nerrors = arg_parse(argc,argv,setInt_argtable);
if (nerrors > 0)
{
arg_print_errors(stdout, endPage, "myprog");
return 0;
}
printf("argc = %d\n", argc); // argc gives the correct number of args
printf("argv[0] = %s\n", argv[0]); // argv[0] gives the correct command name
printf("argv[1] = %s\n", argv[1]); // argv[1] gives the correct value
printf("argInt->ival[0] = %d\n", argInt->ival[0]); // argInt->ival[0] gives random value
return 0;
}
void MyClass::main(void)
{
// Callback pointer initialisation
_callback = this;
/* Initializing the console */
esp_console_config_t console_config
{
256,
8,
atoi(LOG_COLOR_CYAN),
0
};
ESP_ERROR_CHECK( esp_console_init(&console_config) );
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within
* single line.
*/
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
/* Set command history size */
linenoiseHistorySetMaxLen(100);
esp_console_register_help_command();
//
// Feeding my console with argtable parameters
//
esp_console_cmd_t consoleCmd;
consoleCmd.command = "setInt";
consoleCmd.func = &_setInt;
consoleCmd.help = "Trying to set a integer argument";
consoleCmd.argtable = setInt_argtable;
esp_console_cmd_register(&consoleCmd);
/* Main loop */
while(true)
{
// Getting command from user
}
}
Is my approach of using callback member function good ?
Any idea of what is my problem and how I could solve it ?
Thanks in advance for your answers.
After being copying/pasting very simple sample codes found on internet, I finally found what was the problem :
I was including <argtable3/argtable3.h> after "myclass.h"
It took me almost 2 days for a dumb error...
But if somebody has an explanation about why the inclusion order was allowing me to compile the program but making a "corrupted" binary, feel free to answer !
I have install MPI and found simple example of thread that I'm don't fully understand. Can I get a simple example of MPI thread that prints something. Thanks
MPI_Init(&argc, &argv);
int errs = 0;
int provided, flag, claimed;
MPI_Init_thread(0, 0, MPI_THREAD_MULTIPLE, &provided); //what does it MPI_THREAD_MULTIPLE mean
MPI_Is_thread_main(&flag); //why there is flag here
if (!flag) {
errs++; //why there is counter for errs
printf("..."); fflush(stdout); // doesn't print anything
}
MPI_Finalize();
//return errs; I get error here
Is there any relatively "standard" design to auto restart a Qt application program, when it crashes abnormally?
Specific to Windows, do I have to use any windows service?
Or if I have to write another program separately, then how to do that?
Here's how you might do it using a single application that can act either as a monitor or as business logic. It's akin to Jon Harper's answer, except in code, not prose :)
Of Note
The monitor should not instantiate a QApplication nor QGuiApplication: it has no UI. Otherwise, redundant running process indicators will appear on some platforms (i.e. OS X, Win 10).
The monitor/business logic selection is achieved via setting an environment variable in the called process.
Passing the monitor/business logic selection via command line arguments is problematic, as the command line switch would need to be filtered out -- doing that portably without running into corner cases is tricky.
The monitor process forwards the console I/O of the business logic process, as well as the return code.
// https://github.com/KubaO/stackoverflown/tree/master/questions/appmonitor-37524491
#include <QtWidgets>
#include <cstdlib>
#if defined(Q_OS_WIN32)
#include <windows.h>
#else
static void DebugBreak() { abort(); }
#endif
static int businessLogicMain(int &argc, char **argv) {
QApplication app{argc, argv};
qDebug() << __FUNCTION__ << app.arguments();
QWidget w;
QHBoxLayout layout{&w};
QPushButton crash{"Crash"}; // purposefully crash for testing
QPushButton quit{"Quit"}; // graceful exit, which doesn't need restart
layout.addWidget(&crash);
layout.addWidget(&quit);
w.show();
QObject::connect(&crash, &QPushButton::clicked, DebugBreak);
QObject::connect(&quit, &QPushButton::clicked, &QCoreApplication::quit);
return app.exec();
}
static char const kRunLogic[] = "run__business__logic";
static char const kRunLogicValue[] = "run__business__logic";
#if defined(Q_OS_WIN32)
static QString getWindowsCommandLineArguments() {
const wchar_t *args = GetCommandLine();
bool oddBackslash = false, quoted = false, whitespace = false;
// skip the executable name according to Windows command line parsing rules
while (auto c = *args) {
if (c == L'\\')
oddBackslash ^= 1;
else if (c == L'"')
quoted ^= !oddBackslash;
else if (c == L' ' || c == L'\t')
whitespace = !quoted;
else if (whitespace)
break;
else
oddBackslash = false;
args++;
}
return QString::fromRawData(reinterpret_cast<const QChar*>(args), lstrlen(args));
}
#endif
static int monitorMain(int &argc, char **argv) {
#if !defined(Q_OS_WIN32)
QStringList args;
args.reserve(argc-1);
for (int i = 1; i < argc; ++i)
args << QString::fromLocal8Bit(argv[i]);
#endif
QCoreApplication app{argc, argv};
QProcess proc;
auto onFinished = [&](int retcode, QProcess::ExitStatus status) {
qDebug() << status;
if (status == QProcess::CrashExit)
proc.start(); // restart the app if the app crashed
else
app.exit(retcode); // no restart required
};
QObject::connect(&proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), onFinished);
auto env = QProcessEnvironment::systemEnvironment();
env.insert(kRunLogic, kRunLogicValue);
proc.setProgram(app.applicationFilePath()); // logic and monitor are the same executable
#if defined(Q_OS_WIN32)
SetErrorMode(SEM_NOGPFAULTERRORBOX); // disable Windows error reporting
proc.setNativeArguments(getWindowsCommandLineArguments()); // pass command line arguments natively
env.insert("QT_LOGGING_TO_CONSOLE", "1"); // ensure that the debug output gets passed along
#else
proc.setArguments(args);
#endif
proc.setProcessEnvironment(env);
proc.setProcessChannelMode(QProcess::ForwardedChannels);
proc.start();
return app.exec();
}
int main(int argc, char **argv) {
if (qgetenv(kRunLogic) != kRunLogicValue)
return monitorMain(argc, argv);
else
return qunsetenv(kRunLogic), businessLogicMain(argc, argv);
}
If an application crashes, it's done.
Your monitor idea is a good one, and can be achieved using QProcess. Use the "monitor" to bootstrap your actual application. To do this, implement a monitoring object with a QProcess member. In pseudocode:
class MonitorObject : public QObject
{
...
public Q_SLOTS:
void onStarted();
void onFinished(int, QProcess::ExitStatus);
...
private:
QProcess m_process;
}
Then in main:
Create a QCoreApplication and a monitoring object on the stack.
Send a queued signal to your monitor object so it knows when the main event loop starts. You can achieve this using QMetaObject::invoke with a Qt::QueuedConnection:
int main(...)
{
QCoreApplication app;
MonitorObject monitor;
... // other initialization code here
QMetaObject::invoke(&monitor, "onStarted", Qt::QueuedConnection);
return app.exec();
}
And in your MonitorObject:
Connect QProcess's finished signal to onFinished.
When MonitorObject::onStarted is called, start the process.
When the QProcess::finished signal fires, either restart the offending program or exit, depending on the exitCode argument in the emitted signal.
I don't know of any standard Qt method for restarting apps when they crash. But there is a nice class available which makes writing a supervisor/monitor class very easy. It is called QProcess.
You can start the process like this:
monitorClass::startProcess(QString commandLine) // e.g. "c:\mytestapp.exe param1 param2"
{
mp_Process = new QProcess(this);
mp_Process->start(commandLine);
mp_Process->waitForStarted();
// Start a timer
mp_Timer->start(1000);
}
Then when the timer expires (every second - or whatever)
void monitorClass::TimerExpired(void)
{
switch (mp_Process->state())
{
default:
case QProcess::NotRunning:
{
qDebug("Process has stopped un-expectedly\n");
// Tell the supervisor that the process has terminated
// restart the process
startProcess("c:\mytestapp.exe param1 param2"); // just an example
break;
}
case QProcess::Starting:
case QProcess::Running:
{
qDebug("Process is running ok\n");
break;
}
}
}
Note
This is really pseudo code, its not a compilable example - it is just to show you roughly the how easy it is to do this with QProcess...
I am trying to retreive content of websice in c++ usind SDL but it is giving me this error:
'SDL_main' : must return a value
my code is:
#include <iostream>
#include "SDL.h"
#include "SDL_net.h"
#include <cstring>
int main(int argc,char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDLNet_Init();
IPaddress ip;
SDLNet_ResolveHost(&ip,"www.linux.org",80);
const char* http="GET / HTTP/1.1\nHost: www.linux.org\n\n";
TCPsocket client=SDLNet_TCP_Open(&ip);
SDLNet_TCP_Send(client,http,strlen(http)+1);
char text[10000];
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
SDLNet_TCP_Close(client);
SDLNet_Quit();
SDL_Quit();
}
When I put return 0; at the end, it built project but it finished immediately after that
(I am using vs2012)
UPDATE
cout<<"Some message";
doesn't print anything, is it possible that I have configured my imports wrong? are those additional dependencies right?
SDL.lib;SDL_net.lib;SDLmain.lib
I don't know what else could be wrong ...
It's because SDL defines a macro like this:
#define main SDL_main
So the function you've written is actually called SDL_main and like any other function that is not the actual main function, if it doesn't return void, you have to give it a return statement.
because your code doesn't loop forever it just returns 0 after first pass, you need to make a loop like:
while(1){
sdl_events event;
switch(event){
//handle events, drawings and so on
...
...
...
case SDL_QUIT:
exit (0);
break;
}
}
http://sdl.beuc.net/sdl.wiki/OpenGL_Full_Example
UPDATE
you may also have some problem connecting to host so you could check if connection succeed like this:
#define MAXLEN 1024
int result;
char msg[MAXLEN];
result = SDLNet_TCP_Recv(sock,msg,MAXLEN-1);
if(result <= 0) {
// TCP Connection is broken. (because of error or closure)
SDLNet_TCP_Close(sock);
exit(1);
}
else {
msg[result] = 0;
printf("Received: \"%s\"\n",msg);
}
UPDATE 2
change this:
while(SDLNet_TCP_Recv(client,text,10000))
std::cout << text;
to this:
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
UPDATE 3
try this, put your receive part in this if statement
if(SDLNet_SocketReady(client) == 1)
{
while(SDLNet_TCP_Recv(client,text,9999))
std::cout << text;
}
if this still doesn't work I suggest to use QT sockets or Boost asio, both async and more intuitive
I did check the example reverse_client_cb with the reverse_worker as a worker.
The worker is getting called and executed but not a single callback ( complete,fail,etc) is getting called in the client.
Below is a sample worker and client that I wrote to check the same, but, same problem.
Is there any configuration that's need to be done in gearman or in the way the worker and clients are executed?
sampleworker.cc
void* myfunc(gearman_job_st *job, void *data,size_t *size,gearman_return_t *ret)
{
printf("\nmyfunc called\n");
*ret=GEARMAN_SUCCESS;
char *result=(char*)calloc(30,sizeof(char));
strcpy(result,"work completed");
*size=30;
return result;
}
int main(int args,char* argv[])
{
gearman_worker_st worker;
gearman_worker_create(&worker);
gearman_worker_add_server(&worker,"localhost",0);
gearman_return_t ret = gearman_worker_add_function(&worker,"sample",0,myfunc,NULL);
while(1) gearman_worker_work(&worker);
gearman_worker_free(&worker);
return 0;
}
sampleclient.cc
static gearman_return_t complete(gearman_task_st *task)
{
printf("Completed: %s %.*s\n", gearman_task_job_handle(task),
(int)gearman_task_data_size(task), (char *)gearman_task_data(task));
return GEARMAN_SUCCESS;
}
static gearman_return_t fail(gearman_task_st *task)
{
printf("Failed: %s\n", gearman_task_job_handle(task));
return GEARMAN_SUCCESS;
}
int main(int args,char* argv[])
{
gearman_client_st client;
gearman_return_t ret;
gearman_client_create(&client);
gearman_client_add_server(&client,"localhost",0);
gearman_task_st task,*task2;
gearman_client_add_task(&client,&task,NULL,"sample",NULL,argv[1],(size_t)strlen(argv[1]),&ret);
gearman_client_set_complete_fn(&client, &complete);
gearman_client_set_fail_fn(&client, &fail);
gearman_client_run_tasks(&client);
gearman_client_free(&client);
return 0;
}
usage
./sampleworker
./sampleclient Hello
"myfunc called" getting printed and the client is also waiting till the worker completes the job. But nothing is printed from complete or fail functions
got it.
I removed the following libs which was installed and now I'm getting all the callbacks.
libgearman-client-async-perl - Asynchronous client for gearman distributed job system
libgearman-client-perl - Client for gearman distributed job system.
in my opinion. your made some mistake in function invoking sequence.
gearman_client_set_complete_fn(&client, &complete);
gearman_client_set_fail_fn(&client, &fail);
// the function must be called after set_complete_fn
gearman_client_add_task
gearman_client_run_tasks(&client);