How can Tcl_CreateInterp end up in an inifinite loop? - c++

I'm using Tcl library version 8.6.4 (compiled with Visual Studio 2015, 64bits) to interpret some Tcl commands from a C/C++ program.
I noticed that if I create interpreters from different threads, the second one ends up in an infinite loop:
#include "tcl.h"
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
void runScript()
{
Tcl_Interp* pInterp = Tcl_CreateInterp();
std::string sTclPath = boost::filesystem::current_path().string() + "/../../stg/Debug/lib/tcl";
const char* setvalue = Tcl_SetVar( pInterp, "tcl_library", sTclPath.c_str(), TCL_GLOBAL_ONLY );
assert( setvalue != NULL );
int i = Tcl_Init( pInterp );
assert( i == TCL_OK );
int nTclResult = Tcl_Eval( pInterp, "puts \"Hello\"" );
assert( nTclResult == TCL_OK );
Tcl_DeleteInterp( pInterp );
}
int main( int argc, char* argv[] )
{
Tcl_FindExecutable(NULL);
runScript();
runScript();
boost::thread thrd1( runScript );
thrd1.join(); // works OK
boost::thread thrd2( runScript );
thrd2.join(); // never joins
return 1;
}
Infinite loop is here, within Tcl source code:
void
TclInitNotifier(void)
{
ThreadSpecificData *tsdPtr;
Tcl_ThreadId threadId = Tcl_GetCurrentThread();
Tcl_MutexLock(&listLock);
for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId;
tsdPtr = tsdPtr->nextPtr) {
/* Empty loop body. */
}
// I never exit this loop because, after first thread was joined
// at some point tsdPtr == tsdPtr->nextPtr
Am I doing something wrong? Is there any special function call I'm missing?
Note: TCL_THREADS was not set while I compiled Tcl. However, I feel like I'm doing nothing wrong here. Also, adding
/* Empty loop body. */
if ( tsdPtr != NULL && tsdPtr->nextPtr == tsdPtr )
{
tsdPtr = NULL;
break;
}
within the loop apparently fixes the issue. But I'm not very confident in modifying 3rd party library source code...

After reporting a bug to Tcl team, I was asked to try again with Tcl library compiled with TCL_THREADS enabled. It fixed the issue.
TCL_THREADS was disabled because I compiled on windows using a CMake Lists.txt file I found on the web: this one was actually written for Linux and disabled thread support because it was unable to find pthread on my machine. I finally compiled Tcl libraries using the scripts provided by the Tcl team: threading is enabled by default and the infinite loop is gone!

Related

Under which conditions is renaming a file an atomic operation on Linux?

Assumption
According to the documentation, calling rename on Linux performs an atomic replace:
If newpath already exists, it will be atomically replaced, so that there is no point at which another process attempting to access newpath will find it missing.
Contradiction
However, if I run a simple parallel test, with each thread running the following operations:
create a file foo<thread_id>
rename foo<thread_id> to cache_file (cache_file is the same for every thread)
hard link cache_file to bar<thread_id>
it will eventually fail to create the hard link with the following error:
filesystem error: cannot create hard link: No such file or directory [/app/cache_file] [/app/bar1]. So it seems that the replacement of cache_file is not atomic, as concurrently creating a hard link causes an error. (Note that cache_file is actually stored in a content addressable storage, so the overwrite shouldn't do any harm, as the content of the replaced file and the replacement file is exactly the same.)
Question
Shouldn't the hard link creation always succeed if the replacement operation is atomic, so that the created hard link refers to either the replaced file or the replacement file?
See the minimal working example on godbolt or here:
#include <thread>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
auto myrename(std::filesystem::path const& from,
std::filesystem::path const& to, int variant) -> bool {
switch (variant) {
case 0: // c++ rename
std::filesystem::rename(from, to);
return true;
case 1: // c rename
return std::rename(from.c_str(), to.c_str()) == 0;
case 2: // linux rename (same as std::rename?)
return rename(from.c_str(), to.c_str()) == 0;
case 3: // linux link and unlink (no overwrite)
return (link(from.c_str(), to.c_str()) == 0 or errno == EEXIST)
and unlink(from.c_str()) == 0;
case 4: // linux renameat2 without overwrite
return renameat2(0, from.c_str(), 0, to.c_str(), RENAME_NOREPLACE) == 0
or (errno == EEXIST and unlink(from.c_str()) == 0);
default:
return false;
}
}
auto mylink(std::filesystem::path const& from, std::filesystem::path const& to,
int variant) -> bool {
if (std::filesystem::exists(to)) std::filesystem::remove(to);
switch (variant) {
case 0: // c++ hard link
std::filesystem::create_hard_link(from, to);
return true;
case 1: // linux link
return link(from.c_str(), to.c_str()) == 0;
default:
return false;
}
}
auto create_store_stage(std::string const& id) noexcept -> bool {
try {
auto cwd = std::filesystem::current_path();
auto cache = cwd / "cache_file"; // common
auto ifile = cwd / ("foo" + id); // thread local
auto ofile = cwd / ("bar" + id); // thread local
return std::ofstream{ifile}.put('x') // 1. create input file
and myrename(ifile, cache, 0) // 2. store in cache
and mylink(cache, ofile, 0); // 3. hard link to output file
} catch (std::exception const& e) {
std::cout << "caught exception: " << e.what() << std::endl;
return false;
}
}
int main(int argc, const char *argv[]) {
bool fail{};
std::vector<std::thread> threads{};
for (int i{}; i < std::thread::hardware_concurrency(); ++i) {
threads.emplace_back([id = std::to_string(i), &fail]{
while (not fail and create_store_stage(id)) {}
if (errno) perror(("thread " + id + " failed with error").c_str());
fail = true;
});
}
std::for_each(threads.begin(), threads.end(), [](auto& t) { t.join(); });
return 0;
}
Additional Notes
tested on Debian 11 (Kernel 5.10.0) and Ubuntu 20.04 (Kernel 5.8.0)
tested with GCC 9.3/10.2 and Clang 10.0.0/11.0.0 (although I don't expect the compiler to be the issue)
myrename() variants 3 and 4 work correctly (both do not overwrite, which is fine for a content addressable storage)
as expected, neither variant 0 nor 1 of mylink() does make any difference (both use link(), according to strace)
interesting: on WSL2 with Ubuntu 20.04 (Kernel 4.4.0) the myrename() variants 0, 1, and 2 work correctly, but 3 and 4 fail with filesystem error: cannot create hard link: Invalid argument [/app/cache_file] [/app/bar3] and Invalid argument, respectively
*Update
as pointed out by the busybee, link() should be atomic as well. The Linux man pages do not mention any atomic properties, while the POSIX specification explicitly does:
The link() function shall atomically create a new link for the existing file and the link count of the file shall be incremented by one.
as mentioned by numzero, this could be an unintended side-effect. But I did some testing and this behavior dates back to at least Kernel version 2.6.32.

Making directory with vitual studio 2012 coding in c++

Good evening everyone, please I'm writing a Library management application in c++ using virtual studio 2012. I had already writing some codes using Dev c++ it worked but when I switched to visual studio it gives error. It involves creating folders and checking if the folders were actually created. That is using dir and mkdir.
Windows and Linux (POSIX) don't support the same API for most file system functions. You can use Microsoft's platform-specific APIs like CreateDirectory() or use the POSIX-like versions like _mkdir().
If you have a more recent C++ compiler / standard library, you can use the experimental filesystem library that is slated to become part of standard C++, perhaps as early as C++17. If not, you can use Boost.Filesystem from which the pre-standard experimental library was drawn.
Here's a complete, minimal example using Boost.Filesystem, which will work on both Windows and Linux without modification:
#include <iostream>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main()
{
if( !fs::exists( "my_dir" ) )
{
if( fs::create_directory( "my_dir" ) )
{
std::cout << "Directory created!\n";
}
}
}
See it run: Coliru.
Here's the same code but with std::experimental::filesystem: Coliru.
You would need the appropriate include and linker paths setup in your build system for either of these to work locally. The biggest "gotcha" using the filesystem is that it throws exceptions for a lot of errors by default. You can either setup try/catch blocks at the appropriate places or pass in an error code param to make it return the status there instead.
#include <stdio.h>
#include <windows.h>
int main() {
if (!CreateDirectoryA("C:\\ABC123", NULL))
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
printf("Already Exists");
}else if (GetLastError()== ERROR_PATH_NOT_FOUND)
{
printf("Path not found");
}
}else{
printf("Created..");
}
}
simple function will do.
Thanks alot guys but I found this that solved my problem
#include <iostream>
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
void main( void )
{
if( _mkdir( "\\testtmp" ) == 0 )
{
printf( "Directory '\\testtmp' was successfully created\n" );
system( "dir \\testtmp" );
if( _rmdir( "\\testtmp" ) == 0 )
printf( "Directory '\\testtmp' was successfully removed\n" );
else
printf( "Problem removing directory '\\testtmp'\n" );
}
else
printf( "Problem creating directory '\\testtmp'\n" );
int a;
cin >> a;
}
the cin >> a; is just to keep the output screen so I can see the result

LuaPlus: How to make a function return a table?

I'm wondering how I you can create and register a function from the C++-side that returns a table when called from the Lua-side.
I've tried a lot of things but nothing did really work. :/
(sorry for the long code)
This for example won't work, because Register() expects a "luaCFunction"-styled function:
LuaPlus::LuaObject Test( LuaPlus::LuaState* state ) {
int top = state->GetTop();
std::string var( state->ToString(1) );
LuaPlus::LuaObject tableObj(state);
tableObj.AssignNewTable(state);
if (var == "aaa")
tableObj.SetString("x", "ABC");
else if (var == "bbb")
tableObj.SetString("x", "DEF");
tableObj.SetString("y", "XYZ");
return tableObj;
}
int main()
{
LuaPlus::LuaState* L = LuaPlus::LuaState::Create(true);
//without true I can't access the standard libraries like "math.","string."...
//with true, GetLastError returns 2 though (ERROR_FILE_NOT_FOUND)
//no side effects noticed though
LuaPlus::LuaObject globals = L->GetGlobals();
globals.Register("Test",Test);
char pPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH,pPath);
strcat_s(pPath,MAX_PATH,"\\test.lua");
if(L->DoFile(pPath)) {
if( L->GetTop() == 1 ) // An error occured
std::cout << "An error occured: " << L->CheckString(1) << std::endl;
}
}
When I try to set it up as a luaCFunction-function it just crashes (0x3) and says:
Assertion failed: 0, file C:\......\luafunction.h, line 41
int Test( LuaPlus::LuaState* state ) {
int top = state->GetTop();
std::string var( state->ToString(1) );
LuaPlus::LuaObject tableObj(state);
tableObj.AssignNewTable(state);
if (var == "aaa")
tableObj.SetString("x", "ABC");
else if (var == "bbb")
tableObj.SetString("x", "DEF");
tableObj.SetString("y", "XYZ");
tableObj.Push();
return state->GetTop() - top;
}
For clarification: from the Lua side I wanted it to be callable like:
myVar = Test("aaa")
Print(myVar) -- output: ABC
EDIT: The Print function comes from here. And was basically the cause for this to not work. Print can only print strings not tables... The C++ code from above works fine if you just return 1.
This is the documentation that came with my LuaPlus version btw: http://luaplus.funpic.de/
I really hope you can help me.. I'm already starting to think that it is not possible. :'(
edit:
I totally forgot to say that using PushStack() lead into an error because "the member does not exist"...
After some painstaking probing from the long comment discussion, I'm posting this answer to help summary the situation and hopefully to offer some useful advice.
The main issue the OP was running into was that the wrong print function was being called in the lua test script. Contrary to the original code shown the real code the OP was testing against was calling Print(myVar) which is a custom provided lua_CFunction and not the builtin print function.
Somehow along the way, this ended up creating some instantiation of template <typename RT> class LuaFunction and calling the overloaded operator()(). From inspecting the luafunction.h from luaPlus any lua errors that occurs inside this call will get swallowed up without any kind of logging (not a good design decision on luaPlus's part):
if (lua_pcall(L, 0, 1, 0)) {
const char* errorString = lua_tostring(L, -1); (void)errorString;
luaplus_assert(0);
}
To help catch future errors like this, I suggest adding a new luaplus_assertlog macro. Specifically, this macro will include the errorString so that the context isn't completely lost and hopefully help with debugging. This change hopefully won't break existing uses of luaplua_assert from other parts of the API. In the long run though, it's probably better to modify luaplus_assert so it actually includes something meaningful.
Anyway here's a diff of the changes made:
LuaPlusInternal.h
## -81,5 +81,6 ##
} // namespace LuaPlus
#if !LUAPLUS_EXCEPTIONS
+#include <stdio.h>
#include <assert.h>
#define luaplus_assert(e) if (!(e)) assert(0)
## -84,5 +85,6 ##
#include <assert.h>
#define luaplus_assert(e) if (!(e)) assert(0)
+#define luaplus_assertlog(e, msg) if (!(e)) { fprintf(stderr, msg); assert(0); }
//(void)0
#define luaplus_throw(e) assert(0)
//(void)0
LuaFunction.h
## -21,7 +21,7 ##
class LuaFunction
{
public:
- LuaFunction(LuaObject& _functionObj)
+ LuaFunction(const LuaObject& _functionObj)
: functionObj(_functionObj) {
}
## -36,7 +36,7 ##
if (lua_pcall(L, 0, 1, 0)) {
const char* errorString = lua_tostring(L, -1); (void)errorString;
- luaplus_assert(0);
+ luaplus_assertlog(0, errorString);
}
return LPCD::Type<RT>::Get(L, -1);
}
In the change above, I opted not to use std::cerr simply because C++ streams tend to be heavier than plain-old C-style io functions. This is especially true if you're using mingw as your toolchain -- the ld linker is unable to eliminate unused C++ stream symbols even if your program never uses it.
With that in place, here's an example where an unprotected call is made to a lua function so you can see the errorString printed out prior to the crash:
// snip...
int main(int argc, const char *argv[])
{
LuaStateAuto L ( LuaState::Create(true) );
LuaObject globals = L->GetGlobals();
globals.Register("Test", Test);
globals.Register("Print", Print);
if(argc > 1)
{
/*
if (L->DoFile(argv[argc - 1]))
std::cout << L->CheckString(1) << '\n';
/*/
L->LoadFile( argv[argc - 1] );
LuaFunction<int> f ( LuaObject (L, -1) );
f();
//*/
}
}
Running the above will trigger the crash but will include a semi-helpful error message:
g++ -Wall -pedantic -O0 -g -I ./Src -I ./Src/LuaPlus/lua51-luaplus/src plustest.cpp -o plustest.exe lua51-luaplus.dll
plustest.exe plustest.lua
plustest.lua:2: bad argument #1 to 'Print' (string expected, got table)Assertion failed!
Program: G:\OSS\luaplus51-all\plustest.exe
File: ./Src/LuaPlus/LuaFunction.h, Line 39
Expression: 0
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
first you may try to register the function using RegisterDirect(), this may avoid lua_CFunction's problem, check the luaplus manual.like this
LuaPlus::LuaObject globals = L->GetGlobals();
globals.RegisterDirect("Test",Test);
second if I remeber to create a table have two solutions,like this
//first
LuaObject globalsObj = state->GetGlobals();
LuaObject myArrayOfStuffTableObj = globalsObj.CreateTable("MyArrayOfStuff");
//second
LuaObject aStandaloneTableObj;
aStandaloneTableObj.AssignNewTable(state);
check whether you have use the right function.
third I remember the lua stack object is not the luaobject, they have a conversion, may be you can try this
LuaStackObject stack1Obj(state, 1);
LuaObject nonStack1Obj = stack1Obj;
forth, like the function Test() you have give above, the table tableObj you have pushing onto the lua stack, you must remember to clear the object.

fatal error: strtok_r.h: No such file or directory (while compiling tesseract-ocr-3.01 in MinGW)

I'm compiling tesseract-ocr-3.01 in MinGW, and I'm getting this error ambigs.cpp:31:22: fatal error: strtok_r.h: No such file or directory
This is the code where the error is:
#ifdef WIN32
#ifndef __GNUC__
#define strtok_r strtok_s
#else
#include "strtok_r.h"
#endif /* __GNUC__ */
#endif /* WIN32 */
Edit
I found this feature request to add strtok_r.h to MinGW. From the comments there:
strtok_r() is an optional POSIX function, required only for
implementations which support POSIX threads. MinGW does not support
POSIX threads; therefore, I don't think that this function has any
place in a base MinGW distribution.
POSIX threads support for MS-Windows is provided by the pthreads-win32
project. Maybe they already provide a strtok_r() implementation. If
so, then you could use it; if not, you might ask them to consider
adding it.
The problem is most easily solved by adding an strtok_r implementation to the project's sources:
char *strtok_r(char *str, const char *delim, char **save)
{
char *res, *last;
if( !save )
return strtok(str, delim);
if( !str && !(str = *save) )
return NULL;
last = str + strlen(str);
if( (*save = res = strtok(str, delim)) )
{
*save += strlen(res);
if( *save < last )
(*save)++;
else
*save = NULL;
}
return res;
}

Octave c++ and VS2010

I'm trying to Use Octave with Visual C++.
I have downloaded octave-3.6.1-vs2010-setup-1.exe. Created a new project, added octave include folder to include path, octinterp.lib and octave.lib to lib path, and I added Octave bin folder as running directory.
The program compiles and runs fine except feval function that causes the exception:
Microsoft C++ exception: octave_execution_exception at memory location 0x0012faef
and on Octave side:
Invalid resizing operation or ambiguous assignment to an out-of-bounds array element.
What am I doing wrong?
Code for a standalone program:
#include <octave/octave.h>
#include <octave/oct.h>
#include <octave/parse.h>
int main(int argc, char **argv)
{
if (octave_main (argc, argv, true))
{
ColumnVector NumRands(2);
NumRands(0) = 10;
NumRands(1) = 1;
octave_value_list f_arg, f_ret;
f_arg(0) = octave_value(NumRands);
f_ret = feval("rand",f_arg,1);
Matrix unis(f_ret(0).matrix_value());
}
else
{
error ("Octave interpreter initialization failed");
}
return 0;
}
Thanks in advance.
I tried it myself, and the problem seems to originate from the feval line.
Now I don't have an explanation as to why, but the problem was solved by simply switching to the "Release" configuration instead of the "Debug" configuration.
I am using the Octave3.6.1_vs2010 build, with VS2010 on WinXP.
Here is the code I tested:
#include <iostream>
#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
int main(int argc, char **argv)
{
// Init Octave interpreter
if (!octave_main(argc, argv, true)) {
error("Octave interpreter initialization failed");
}
// x = rand(10,1)
ColumnVector sz(2);
sz(0) = 10; sz(1) = 1;
octave_value_list in = octave_value(sz);
octave_value_list out = feval("rand", in, 1);
// print random numbers
if (!error_state && out.length () > 0) {
Matrix x( out(0).matrix_value() );
std::cout << "x = \n" << x << std::endl;
}
return 0;
}
with an output:
x =
0.165897
0.0239711
0.957456
0.830028
0.859441
0.513797
0.870601
0.0643697
0.0605021
0.153486
I'd guess that its actually stopped pointing at the next line and the error actually lies at this line:
f_arg(0) = octave_value(NumRands);
You seem to be attempting to get a value (which value?) from a vector and then assigning it to element 0 of a vector that has not been defined as a vector.
I don't really know though ... I've never tried writing octave code like that. I'm just trying to work it out by translating the code to standard matlab/octave code and that line seems really odd to me ...