March 2015

Facebook, Google+, Twitter, Linked In? Don’t bother.

Every now and again, I get some invite to join some social network or to “Confirm I know ${PERSON}”.  It doesn’t really matter what platform you choose, the end result is the same.

There are a couple of reasons I do not participate on these systems.

Number one is that when I get home, I typically cannot be stuffed having much to do with computers.  Sure I’ll be checking what news has happened during the day, I have an RSS aggregator for that.  I’ll check what the weather is doing tomorrow (as a cyclist, this is of high importance).  I’ll check emails, as that is how I keep in touch with people (I know, how quaint, but it works).

Maybe check some public forums/newsgroups.  That’s about it.  I really cannot be stuffed doing much else having fought with computers all day, I’m really not in the mood when I get home.

Second reason is the nature of these social networks.  Much of the interaction happens behind the scenes.  You’re “sharing” to an audience behind closed doors.  That audience has to be a member of that same group to even see your material.  Don’t believe me?  Try to log into Facebook and then go “Friend” a Google+ user and share something with them.  Or how about go log into Google+ and “circle” (is that the term?) a Linked In user.  These new-breed “social” networks are about as anti-social as it gets.

They’re today’s bulletin board system.  I’m sorry, are we really abandoning the World Wide Web for what’s little more than a BBS?  About the only difference I see is that JavaScript and HTML5 replace the ANSI/DEC escape sequences of old.  It’s still an isolated silo from which your information is locked in and only those who have opted into that network can participate.

A forum can be publicly viewed in most cases, in fact forums generally have trouble attracting an audience if they’re not publicly visible.

Finally there’s the privacy.  Sharing what you’re doing in your day to day life is one thing.  You can share a lot without giving much away personally.  “Friend”-ing people however is basically uploading your social graph, one link at a time.  One’s social graph is one of the most personal things one can expose about themselves, and increasingly the privacy policies of these social networks have been found lacking in several aspects.

Companies have been working on sophisticated ways in order to search and map out these social graphs, they would not be doing this if there wasn’t financial incentive to do so.  Knowing who someone’s friends are is the first step in being able to manipulate that person.  I’d rather not be someone’s puppet.

There’s also the phishing risk.  They’re popular sites to try and spoof.  I recently received one alleging to be from The Register author Simon Rockman.  It could be authentic, but then again, anyone could sign up for an account on one of these social network, claim to be someone they’re not, and try to lure you in.  I’ve got no way of verifying this, and with a broken “Reply-to” header, in the bin it goes.

So, next time you think of putting my email address in to a form on a social network page to invite me to join, don’t bother.  I do respond to emails, I even respond to comments left here (unless they’re spam), but I will not respond to social network invites, in fact I may not even receive them.

TC Nathan, the cyclone that just won’t die!

Tropical Cyclone Nathan, Forecast map as of 2:50PM

Tropical Cyclone Nathan, Forecast map as of 2:50PM

This cyclone has harassed the far north once already, wobbled out in the Pacific like a drunken cyclist as a tropical low, has gained strength again and is now making a bee-line for Cape Flattery.

As seen, it also looks like doing the same stunt headed for Gove once it’s finished touching up far north Queensland.  Whoever up there is doing this rain dancing, you can stop now, it’s seriously pissing off the weather gods.

National and IARU REGION III Emergency Frequencies (Please keep clear and listen for emergency traffic)

  • 80m
    • 3.600MHz LSB (IARU III+WICEN)
  • 40m
    • 7.075MHz LSB (WICEN)
    • 7.110MHz LSB (IARU III)
  • 20m
    • 14.125MHz USB (WICEN)
    • 14.300MHz USB (IARU III)
    • 14.183MHz USB: NOT an emergency frequency, but Queensland State WICEN hold a net on this frequency every Sunday morning at around 08:00+10:00 (22:00Z Saturday).
  • 15m
    • 21.190MHz USB (WICEN)
    • 21.360MHz USB (IARU III)
  • 10m
    • 28.450MHz USB (WICEN)

I’ll be keeping an ear out on 14.125MHz in the mornings.

Update 20 March 4:31am: It has made landfall between Cape Melville and Cape Flattery as a category 4 cyclone.

Qt: Creating QSharedPointers from “this”

Hi all,

This is more a note to self for future reference.  Qt has a nice handy reference counting memory management system by means of QSharedPointer and QWeakPointer.  The system is apparently thread-safe and seems to be totally transparent.

One gotcha though, is two QSharedPointer objects cannot share the same pointer unless one is cloned from the other (either directly or via QWeakPointer).  The other is that you must leave deletion of the object to QSharedPointer.  You’ve given it your precious pointer, it has adopted it and while you may call the object, it is no longer yours, so don’t go deleting it.

So you create an object, you want to pass a reference to yourself to some other object.  How?  Like this?

QSharedPointer<MyClass> MyClass::ref() {
    return QSharedPointer<MyClass>(this); /* NO! */
}

No, not like that! That will create QSharedPointer instances left right and centre. Not what you want to do at all. What you need to do, is create the initial reference, but then store a weak reference to it. Then all future calls, you simply call the toStrongRef method of the weak reference to get a QSharedPointer that’s linked to the first one you handed out.

Then, having done this, when you create your new object, you create it with the new keyword as normal, take a QSharedPointer reference to it, then forget all about the original pointer! You can get it back by calling the data method of the pointer object.

To make it simple, here’s a base class you can inherit to do this for you.

    #include <QWeakPointer>
    #include <QSharedPointer>

    /*!
     * Self-Reference helper.  This allows for objects to maintain
     * references to "this" via the QSharedPointer reference-counting
     * smart pointers.
     */
    template<typename T>
    class SelfRef {
        public:
            /*!
             * Get a strong reference to this object.
             */
            QSharedPointer<T>    ref()
            {
                QSharedPointer<T> this_ref(this->this_weak);
                if (this_ref.isNull()) {
                    this_ref = QSharedPointer<T>((T*)this);
                    this->this_weak = this_ref.toWeakRef();
                }
                return this_ref;
            }

            /*!
             * Get a weak reference to this object.
             */
            QWeakPointer<T>        weakRef() const
            {
                return this->this_weak;
            }
        private:
            /*! A weak reference to this object */
            QWeakPointer<T>        this_weak;
    };

Example usage:

#include <iostream>
#include <stdexcept>
#include "SelfRef.h"

class Test : public SelfRef<Test> {
        public:
                Test()
                {
                        std::cout << __func__ << std::endl;
                        this->freed = false;
                }
                ~Test()
                {
                        std::cout << __func__ << std::endl;
                        this->freed = true;
                }

                void test() {
                        if (this->freed)
                                throw std::runtime_error("Already freed!");
                        std::cout
                                << "Test object is at "
                                << (void*)this
                                << std::endl;
                }

                bool                    freed;
                QSharedPointer<Test>    another;
};

int main(void) {
        Test* a = new Test();
        if (a != NULL) {
                QSharedPointer<Test> ref1 = a->ref();
                if (!ref1.isNull()) {
                        QSharedPointer<Test> ref2 = a->ref();
                        ref2->test();
                }
                ref1->test();
        }
        a->test();
        return 0;
}

Note that the line before the return is a deliberate use after free bug to prove the pointer really was freed.  Also note that the idea of setting a boolean flag to indicate the constructor has been called only works here because nothing happens between that use after free attempt and the destructor being called.  Don’t rely on this to see if your object is being called after destruction.  This is what the output session from gdb looks like:

RC=0 stuartl@rikishi /tmp/qtsp $ make CXXFLAGS=-g
g++ -c -g -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -o test.o test.cpp
g++ -Wl,-O1 -o qtsp test.o    -L/usr/lib64/qt4 -lQtGui -L/usr/lib64 -L/usr/lib64/qt4 -L/usr/X11R6/lib -lQtCore -lgthread-2.0 -lglib-2.0 -lpthread 
RC=0 stuartl@rikishi /tmp/qtsp $ gdb ./qtsp 
GNU gdb (Gentoo 7.7.1 p1) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./qtsp...done.
(gdb) r
Starting program: /tmp/qtsp/qtsp 
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Test
Test object is at 0x555555759c90
Test object is at 0x555555759c90
~Test
terminate called after throwing an instance of 'std::runtime_error'
  what():  Already freed!

Program received signal SIGABRT, Aborted.
0x00007ffff5820775 in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff5820775 in raise () from /lib64/libc.so.6
#1  0x00007ffff5821bf8 in abort () from /lib64/libc.so.6
#2  0x00007ffff610cd75 in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
#3  0x00007ffff6109ec8 in ?? () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
#4  0x00007ffff6109f15 in std::terminate() () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
#5  0x00007ffff610a2e9 in __cxa_throw () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
#6  0x0000555555555cea in Test::test (this=0x555555759c90) at test.cpp:20
#7  0x0000555555555315 in main () at test.cpp:41
(gdb) up
#1  0x00007ffff5821bf8 in abort () from /lib64/libc.so.6
(gdb) up
#2  0x00007ffff610cd75 in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
(gdb) up
#3  0x00007ffff6109ec8 in ?? () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
(gdb) up
#4  0x00007ffff6109f15 in std::terminate() () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
(gdb) up
#5  0x00007ffff610a2e9 in __cxa_throw () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.3/libstdc++.so.6
(gdb) up
#6  0x0000555555555cea in Test::test (this=0x555555759c90) at test.cpp:20
20                                      throw std::runtime_error("Already freed!");
(gdb) up
#7  0x0000555555555315 in main () at test.cpp:41
41              a->test();
(gdb) quit
A debugging session is active.

        Inferior 1 [process 17906] will be killed.

Quit anyway? (y or n) y

You’ll notice it fails right on that second last line because the last QSharedPointer went out of scope before this.  This is why you forget all about the pointer once you create the first QSharedPointer.

To remove the temptation to use the pointer directly, you can make all your constructors protected (or private) and use a factory that returns a QSharedPointer to your new object.

A useful macro for doing this:

/*!
 * Create an instance of ClassName with the given arguments
 * and immediately return a reference to it.
 *
 * @returns	QSharedPointer<ClassName> object
 */
#define newRef(ClassName, args ...)	\
	((new ClassName(args))->ref().dynamicCast<ClassName>())

VK4MSL/BM Mk3: 18 months later

Well, it’s been a year and a half since I last posted details about the bicycle mobile station.  Shortly after getting the Talon on the road, setting it up with the top box and lighting, and having gotten the bugs worked out of that set-up, I decided to get a second mounting plate and set my daily commuter up the same way, doing away with the flimsy rear basket in place of a mounting plate for the top box.

VK4MSL/BM today after the trip home from work.

VK4MSL/BM today after the trip home from work.

That particular bike people might recognise from earlier posts, it’s my first real serious commuter bike. Now in her 5th year, has done over 10200km since 2012.  (The Talon has done 5643km in that time.) You can add to that probably another 5000km or so done between 2010 and 2012. It’s had a new rear wheel (a custom one, after having a spate of spoke breakages) and the drive chain has been upgraded to 9-speed. The latter upgrade alone gave it a new lease on life.

Both upgrades being money well spent, as was the upgrade to hydraulic brakes early in the bike’s lifetime. I suppose I’ve spent in those upgrades alone close to $1400, but worth it as it has given me quite good service so far.

As for my time with the top box. Some look at it and quiz me about how much weight it adds. The box itself isn’t that heavy, it just looks it. I can carry a fair bit of luggage, and at present, with my gear and tools in it it weighs 12kg. Heavy, but not too heavy for me to manage.

Initially when I first got it, it was great, but then as things flexed over time, I found I was intermittently getting problems with the top box coming off.  This cost me one HF antenna and today, the top box sports a number of battle-scars as a result.

The fix to this?  Pick a spot inside the top box that’s clear of the pannier rack rails and the rear tyre, and drill a 5mm hole through.  Then, when you mount the top box, insert an M5 bolt through the mounting plate and into the bottom of the top box and tighten with a 5mm wing nut.  The box now will not come loose.

vk4msl-bm-2713

Still lit up like a Christmas tree from this morning’s ride.

The lights still work, and now there’s a small rear-view camera.  On the TODO list is to rig up a 5V USB socket to power that camera with so that it isn’t draining the rather small internal battery (good for 4 hours apparently).

The station has had an upgrade, I bought a new LDG Z-100Plus automatic tuner which I’m yet to fully try out.  This replaces the aging Yaesu FC-700 manual tuner which, although very good, is fiddly to use in a mobile set-up and doesn’t tune 6m easily.

One on-going problem now not so much on the Boulder but on the Talon is an issue with pannier racks failing.  This started happening when I bought the pannier bags, essentially on the side I carry my battery pack (2kg), I repeatedly get the pannier rack failing.  The racks I use are made by Topeak and have a built-in spacer to accomodate disc brake calipers.  This seems to be a weak spot, I’ve now had two racks fail at about the same point.

Interestingly on the Boulder which also has disc brakes, I use the standard version of the same rack, and do not get the same failures.  Both are supposedly rated to 25kg, and my total load would be under 16kg. Something is amiss.

A recurring flaw with the Topeak racks

I’m on the look-out for a more rugged rack that will tolerate this kind of usage, although having seen this, I am inspired to try a DIY solution.  Then if a part fails, I can probably get replacement parts in any typical hardware store.  A hack saw and small drill are not heavy items to carry, and I can therefore get myself out of trouble if problems arise.