Qt5 and GLEW MX => glewInit fails - multithreading

We are migrating our project from Qt 4.8 to 5.4. We use multiple contexts in multiple thread. We use GLEW MX for this purpose (We make the context we desire current then call glewInit() on a local instance of GLEWContextStruct).
I'm trying to change QGLWidget and QGLContext to QOpenGLWidget and QOpenGLContext but I ended up not being able to initialize glew anymore.
GLEW doesn't return an error but glGetError() does.
I did install Qt 5.4 64 with OpenGL version.
Here is the code reduced to a minimum :
#include <QtWidgets/QApplication>
#define GLEW_MX
#define GLEW_STATIC
#include <GL/glew.h>
#include <qopenglcontext.h>
#include <qwindow.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool errQt;
int errGlew;
GLenum errorGL;
QSurfaceFormat requestedFormat;
requestedFormat.setVersion(3, 3);
requestedFormat.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
//Creates the QGLWidget using the current context:
QWindow window;
window.setSurfaceType(QSurface::OpenGLSurface);
window.setFormat(requestedFormat);
window.create();
//Create context
QOpenGLContext context;
context.setFormat(requestedFormat);
errQt = context.create(); //true
//Bind context
context.makeCurrent(&window);
//Glew context creation
GLEWContext* pCtx = new GLEWContext; //All forwards undefined
//Release context
context.doneCurrent();
return 1;
}
Any suggestion ? Is GLEW alright with Qt5.4 ?
EDIT 1 :
It appears the problem is not Qt related. The GLEWContext created doesn't have any function forward defined (all function pointers are undefined). The code has been updated to help the reviewer not lose focus.

I use glewInit() with Qt 5.4 in my project, but I'm using QWindow as my base class, not QOpenGLWidget.
In my ctor I do this:
QRiftWindow::QRiftWindow() {
setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
format.setVersion(4, 3);
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
setFormat(format);
m_context = new QOpenGLContext;
m_context->setFormat(format);
m_context->create();
...
I execute my OpenGL work on a separate thread. Once the thread has started I call an setup method on my class
m_context->makeCurrent(this);
glewExperimental = true;
glewInit();
glGetError();
I've previously done this exact same setup with OpenGL 3.3 and had no issues.

You should actually get a warning about that:
#warning qopenglfunctions.h is not compatible with GLEW, GLEW defines will be undefined
#warning To use GLEW with Qt, do not include or after glew.h
Your "qopenglcontext.h" includes . To answer your question, you can use Qt + GLEW, but u can't easily mix up Qt-opengl with GLEW.

Related

Thread safety of std::cout insertion operator

I've always thought that using std::cout << something was thread safe.
For this little example
#include <iostream>
#include <thread>
void f()
{
std::cout << "Hello from f\n";
}
void g()
{
std::cout << "Hello from g\n";
}
int main()
{
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
}
my expectation was that the order of the two outputs would be undefined (and indeed that is what I observe in practice), but that the calls to operator<< are thread safe.
However, ThreadSanitizer, DRD and Helgrind all seem to give various errors regarding access to std::__1::ios_base::width(long) and std::__1::basic_ios<char, std::__1::char_traits >::fill()
On Compiler Explorer I don't see any errors.
On FreeBSD 13, ThreadSanitizer gives me 3 warnings, the two listed above plus the malloc/memcpy to the underlying i/o buffer.
Again in FreeBSD 13, DRD gives 4 errors, width() and fill() times two for the two threads.
Finally FreeBSD 13 Helgrind gives one known false positive related to TLS in thread creation, fill()and width() twice.
On Fedora 34
No errors with g++ 11.2.1 and ThreadSanitizer
DRD complains about malloc/memcpy in fwrite with g++ compiled exe
Helgrind also complains about fwrite and also for the construction of cout, again with the g++ compiled exe
clang++ 12 ThreadSanitizer complains about fill() and width()
DRD with the clang++ compiler exe complains about fill(), width(), fwrite and one other in start_thread
Helgrind with the clang++ exe complains about some TLS, fill(), width(), fwrite
macOS XCode clang++ ThreadSanitizer generates warnings as well (which will be libc++).
Looking at the libc++ and libstdc++ code I don't see anything at all that protects width(). So I don't understand why there are no complaints on compiler explorer.
I tried running with TSAN_OPTIONS=print_suppressions=1 and there was no more output (g++ Fedora ThreadSanitizer)
There does seem to be some consensus over the width() and fill() calls.
Looking more closely at the libstdc++ source I see that there is
(with some trimming and comments):
// ostream_insert.h
// __n is the length of the string pointed to by __s
template<typename _CharT, typename _Traits>
basic_ostream<_CharT, _Traits>&
__ostream_insert(basic_ostream<_CharT, _Traits>& __out,
const _CharT* __s, streamsize __n)
{
typedef basic_ostream<_CharT, _Traits> __ostream_type;
typedef typename __ostream_type::ios_base __ios_base;
typename __ostream_type::sentry __cerb(__out);
if (__cerb)
{
__try
{
const streamsize __w = __out.width();
if (__w > __n)
{
// snipped
// handle padding
}
else
__ostream_write(__out, __s, __n);
// why no hazard here?
__out.width(0);
}
__out is the stream object, global cout in this case. I don't see anything like locks or atomics.
Any suggestions as to how ThreadSanitizer/g++ is getting a "clean" output?
There is this somewhat cryptic comment
template<typename _CharT, typename _Traits>
basic_ostream<_CharT, _Traits>::sentry::
sentry(basic_ostream<_CharT, _Traits>& __os)
: _M_ok(false), _M_os(__os)
{
// XXX MT
if (__os.tie() && __os.good())
__os.tie()->flush();
The libc++ code looks similar. In iostream
template<class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
__put_character_sequence(basic_ostream<_CharT, _Traits>& __os,
const _CharT* __str, size_t __len)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
typename basic_ostream<_CharT, _Traits>::sentry __s(__os);
if (__s)
{
typedef ostreambuf_iterator<_CharT, _Traits> _Ip;
if (__pad_and_output(_Ip(__os),
__str,
(__os.flags() & ios_base::adjustfield) == ios_base::left ?
__str + __len :
__str,
__str + __len,
__os,
__os.fill()).failed())
__os.setstate(ios_base::badbit | ios_base::failbit);
and in locale
template <class _CharT, class _OutputIterator>
_LIBCPP_HIDDEN
_OutputIterator
__pad_and_output(_OutputIterator __s,
const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
ios_base& __iob, _CharT __fl)
{
streamsize __sz = __oe - __ob;
streamsize __ns = __iob.width();
if (__ns > __sz)
__ns -= __sz;
else
__ns = 0;
for (;__ob < __op; ++__ob, ++__s)
*__s = *__ob;
for (; __ns; --__ns, ++__s)
*__s = __fl;
for (; __ob < __oe; ++__ob, ++__s)
*__s = *__ob;
__iob.width(0);
return __s;
}
Again I see no thread protection, but also this time the tools detect a hazard.
Are these real issues? For plain calls to operator<< the value of width doesn't change, and is always 0.
libstdc++ does not produce the error while libc++ does.
iostream.objects.overview Concurrent access to a synchronized ([ios.members.static]) standard iostream object's formatted and unformatted input ([istream]) and output ([ostream]) functions or a standard C stream by multiple threads does not result in a data race ([intro.multithread]).
So this looks like a libc++ bug to me.
I got the answer from Jonathan Wakely. Makes me feel rather stupid.
The difference is that on Fedora, libstdc++.so contains an explicit instantiation of the iostream classes. libstdc++.so isn't instrumented for ThreadSanitizer so it cannot detect any hazards related to it.

Pubnub library not compiling on Particle Photon

I am trying to publish a message using pubnub on the Particle Photon. The code snippet below comes straight out of the Pubnub example code.
The code will not compile, with the message from the compiler as follows:
PubNub/PubNub.h:87:47: error: expected class-name before '{' token
class PubSubClient: public PubNub_BASE_CLIENT {
^
PubNub/PubNub.h: In constructor 'PubSubClient::PubSubClient()':
PubNub/PubNub.h:23:28: error: class 'PubSubClient' does not have any field named 'WiFiClient'
#define PubNub_BASE_CLIENT WiFiClient
^
The code for this tiny project is as follows:
// This #include statement was automatically added by the Particle IDE.
#include "PubNub/PubNub.h"
char pubkey[] = "<key here>";
char subkey[] = "<key here>";
char channel[] = "Channel";
void setup() {
Serial.begin(9600);
Particle.publish("Serial set up");
PubNub.begin(pubkey, subkey);
}
void loop() {
TCPClient *client;
char msg[64] = "{\"photon\":\"on\"}";
client = PubNub.publish(channel, msg);
client->stop();
Delay (30000);
}
Has anyone had a similar problem, and if so, can you guide me as to how to fix this.
Thanks.
It looks like the library available in Build IDE was in an older version (0.0.1). Fixed, latest version (0.0.2) has been published.
To update library in your app you need to remove the PubNub library from your app in Apps drawer:
And then go to Libraries drawer, find PubNub library, click Include in App, select your app and confirm:

Wemos - oled sparkfun print text does not display

I'm using a led matrix shield (http://www.wemos.cc/Products/oled_shield.html) with a wemos. I'm using Arduino IDE.
The exemples work perfectly (https://github.com/wemos/D1_mini_Examples/tree/master/04.Shields/OLED_Shield/Use_SparkFun_Library)
But when I try to print text, the screen remains empty. Here is my code
#include <Wire.h>
#include <SFE_MicroOLED.h> // Include the SFE_MicroOLED library
#define PIN_RESET 255
#define DC_JUMPER 0
MicroOLED oled(PIN_RESET, DC_JUMPER);
void setup()
{
oled.begin();
oled.clear(ALL);
oled.clear(PAGE);
oled.display();
oled.setFontType(0);
oled.setCursor(0, 0);
oled.print("Hello, world");
oled.display();
}
void loop()
{
}
Any idea ?
I solved the issue. I modified SFE_MicroOLED lib.
The fonts are loaded in the program memory (via PROGMEM directive). This makes the code fail on wemos.
I remove PROGMEM directive on a fork of this lib (https://github.com/landru29/SparkFun_Micro_OLED_Arduino_Library)
I just check if the arch is ARDUINO_ESP8266_NODEMCU
https://github.com/landru29/SparkFun_Micro_OLED_Arduino_Library/blob/master/src/util/7segment.h#L37 (idem for all other font files in the same folder)

Linux alternative to _NSGetExecutablePath?

Is it possible to side-step _NSGetExecutablePath on Ubuntu Linux in place of a non-Apple specific approach?
I am trying to compile the following code on Ubuntu: https://github.com/Bohdan-Khomtchouk/HeatmapGenerator/blob/master/HeatmapGenerator2_Macintosh_OSX.cxx
As per this prior question that I asked: fatal error: mach-o/dyld.h: No such file or directory, I decided to comment out line 52 and am wondering if there is a general cross-platform (non-Apple specific) way that I can rewrite the code block of line 567 (the _NSGetExecutablePath block) in a manner that is non-Apple specific.
Alen Stojanov's answer to Programmatically retrieving the absolute path of an OS X command-line app and also How do you determine the full path of the currently running executable in go? gave me some ideas on where to start but I want to make certain that I am on the right track here before I go about doing this.
Is there a way to modify _NSGetExecutablePath to be compatible with Ubuntu Linux?
Currently, I am experiencing the following compiler error:
HeatmapGenerator_Macintosh_OSX.cxx:568:13: error: use of undeclared identifier
'_NSGetExecutablePath'
if (_NSGetExecutablePath(path, &size) == 0)
Basic idea how to do it in a way that should be portable across POSIX systems:
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
static char *path;
const char *appPath(void)
{
return path;
}
static void cleanup()
{
free(path);
}
int main(int argc, char **argv)
{
path = realpath(argv[0], 0);
if (!path)
{
perror("realpath");
return 1;
}
atexit(&cleanup);
printf("App path: %s\n", appPath());
return 0;
}
You can define an own module for it, just pass it argv[0] and export the appPath() function from a header.
edit: replaced exported variable by accessor method

ELF weak import / fallback stubs for glibc functions

I am trying to make our program runnable on some old Linux versions. One common import that prevents it is __longjmp_chk, added in glibc 2.11 but missing in older ones. One "solution" is to use -D_FORTIFY_SOURCE=0 but this turns off other fortify functions (__printf_chk etc) which are present in the target libc. Is there a way to make __longjmp_chk a "weak import" which would use the function from libc.so.6 if present, and fall back to local stub if not?
Is there a way to make __longjmp_chk a "weak import" which would use
the function from libc.so.6 if present, and fall back to local stub
if not?
I'd say yes, using dlsym() to check for __longjmp_chk and acting accordingly:
/* cc -ldl */
#define _GNU_SOURCE
#include <setjmp.h>
#include <stdio.h>
#include <dlfcn.h>
void __longjmp_chk(sigjmp_buf env, int val)
{
void (*p)(sigjmp_buf, int) = dlsym(RTLD_NEXT, "__longjmp_chk");
if (p)
printf("use the function from libc\n"),
p(env, val);
else
{
printf("falling back to local stub\n");
/* local stub - whatever that may be */
}
}
main()
{ // try it
sigjmp_buf env;
while (!setjmp(env)) __longjmp_chk(env, 1);
return 0;
}
I am trying to make our program runnable on some old Linux versions.
There are only a few ways to make this work, and most of them are enumerated here.
Is there a way to make __longjmp_chk a "weak import".
No.

Resources