C/C++: Set and Get the name of a pthread

Naming a pthread using meaningful names, can be a very useful feature for debugging multi-threaded applications as it can make your logs very informative.
For this reason, we are presenting two examples demonstrating the use of names in pthreads.

Example 1: The pthread decides for its name

The following code, creates a pthread which later, it will give itself a meaningful name.

pthread_self_named.c (compressed) (7 downloads)
// #define _GNU_SOURCE is needed for the resolution of the following warnings
//warning: implicit declaration of function ‘pthread_setname_np’ [-Wimplicit-function-declaration]
//warning: implicit declaration of function ‘pthread_getname_np’ [-Wimplicit-function-declaration]
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <asm/errno.h>
#include <errno.h>
// #include <stdlib.h> is needed for the resolution of EXIT_SUCCESS
#include <stdlib.h>

//The thread name is a meaningful C language string, whose length is restricted to 16 characters, including the terminating null byte.
#define MAX_LENGTH_PTHREAD_NAME (16)

struct thread_info_t
{
    // Used to identify a thread.
    pthread_t thread_id;
};

// This is the thread that will be called by pthread_create() and it will be executed by the new thread.
void *self_named_thread(void *data)
{
    // We know that the input data pointer is pointing to a thread_info_t so we are casting it to the right type.
    struct thread_info_t *thread_info = (struct thread_info_t *) data;

    const int setname_rv = pthread_setname_np(thread_info->thread_id, "Tom Hanks");
    if (setname_rv)
    {
        errno = setname_rv;
        perror("Could not set pthread name");
    }

    char thread_name[MAX_LENGTH_PTHREAD_NAME];
    const int getname_rv = pthread_getname_np(thread_info->thread_id, thread_name, MAX_LENGTH_PTHREAD_NAME);
    if (getname_rv)
    {
        errno = getname_rv;
        perror("Could not get pthread name");
    }
    //This function always succeeds, returning the calling thread's ID.
    const pthread_t tid = pthread_self();
    //Usually pthread_t is defined as follows:
    //typedef unsigned long int pthread_t;
    //so we print pthread_t as an unsigned long int
    fprintf(stdout, "I am thread with ID '%lu', my name is '%s' and I gave me my name by myself\n", tid, thread_name );

    return NULL;
}

int main()
{
    struct thread_info_t thread_info;

    const int create_rv = pthread_create(&(thread_info.thread_id), NULL, &self_named_thread, (void *) &thread_info);
    if (create_rv)
    {
        errno = create_rv;
        perror("Could not create thread");
        return EXIT_FAILURE;
    }
    // The pthread_join() function suspends execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
    const int join_rv = pthread_join(thread_info.thread_id, NULL);
    if (join_rv)
    {
        errno = create_rv;
        perror("Could not join thread");
    }
    return EXIT_SUCCESS;
}

pthread_self_named.c (compressed) (7 downloads)

Example 2: The parent decides for the pthread name

The next code, creates a pthread and the parent gives the thread a meaningful name.

pthread_named_by_parent.c (compressed) (8 downloads)
// #define _GNU_SOURCE is needed for the resolution of the following warnings
//warning: implicit declaration of function ‘pthread_setname_np’ [-Wimplicit-function-declaration]
//warning: implicit declaration of function ‘pthread_getname_np’ [-Wimplicit-function-declaration]
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <asm/errno.h>
#include <errno.h>
// #include <stdlib.h> is needed for the resolution of EXIT_SUCCESS
#include <stdlib.h>
// #include <unistd.h> is needed for the resolution of unsigned int sleep(unsigned int seconds);
#include <unistd.h>

//The thread name is a meaningful C language string, whose length is restricted to 16 characters, including the terminating null byte.
#define MAX_LENGTH_PTHREAD_NAME (16)

struct thread_info_t
{
    // Used to identify a thread.
    pthread_t thread_id;
};

// This is the thread that will be called by pthread_create() and it will be executed by the new thread.
void *self_named_thread(void *data)
{
    // We know that the input data pointer is pointing to a thread_info_t so we are casting it to the right type.
    struct thread_info_t *thread_info = (struct thread_info_t *) data;

    //Added an artificial delay for the sake of the example.
    //Making sure the parent thread gave the pthread a name.
    sleep(1);

    char thread_name[MAX_LENGTH_PTHREAD_NAME];
    const int getname_rv = pthread_getname_np(thread_info->thread_id, thread_name, MAX_LENGTH_PTHREAD_NAME);
    if (getname_rv)
    {
        errno = getname_rv;
        perror("Could not get pthread name");
    }
    //This function always succeeds, returning the calling thread's ID.
    const pthread_t tid = pthread_self();
    //Usually pthread_t is defined as follows:
    //typedef unsigned long int pthread_t;
    //so we print pthread_t as an unsigned long int
    fprintf(stdout, "I am thread with ID '%lu', my name is '%s' and my parent gave me my name\n", tid, thread_name );

    return NULL;
}

int main()
{
    struct thread_info_t thread_info;

    const int create_rv = pthread_create(&(thread_info.thread_id), NULL, &self_named_thread, (void *) &thread_info);
    if (create_rv)
    {
        errno = create_rv;
        perror("Could not create thread");
        return EXIT_FAILURE;
    }

    const int setname_rv = pthread_setname_np(thread_info.thread_id, "Bob Marley");
    if (setname_rv)
    {
        errno = setname_rv;
        perror("Could not set pthread name");
    }

    // The pthread_join() function suspends execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
    const int join_rv = pthread_join(thread_info.thread_id, NULL);
    if (join_rv)
    {
        errno = create_rv;
        perror("Could not join thread");
    }
    return EXIT_SUCCESS;
}

pthread_named_by_parent.c (compressed) (8 downloads)

Cyprus – Prepaid Cards – Check Remaining Balance and Expiration Date

Cyta – soeasy Pay As You Go

To check the remaining balance and the expiration date of your SIM card, type *110# and press call/dial.
To find out the current information on your bonuses (e.g. free SMS) type *110*1# and then press call/dial.

PrimeTel – Pay As You Go Kartokiniti

To find out your account balance and expiration date, type *133# and press call/dial.
To find out the remaining balance of your bonus, type *140# and press call/dial.

MTN – Pay As You Go

You can find out what your available balance is and when will your subscription expire by typing *202# and then pressing call/dial.


Unmanned Aerial Vehicles – Innovation and Challenges

The IEEE and the Cyprus Computer Society present the state of art of drone technologies and applications.

3 October 2017
University of Cyprus
Building KOD 07, Room 10
Starts at 17.00
Free Food and Drinks

Presentations:

Flyer (15 downloads)

Program (11 downloads)

  • Presentations on the state of art of drone technologies & applications
  • Drone Piloting
  • Prize draw for IEEE student members:
    One-day piloting course worth €250, by DJI Cyprus

Program

  • 17:00-17:25: “UAV in Emergency Response: Research and Innovation Challenges”
    Dr. Panayiotis Kolios, KIOS Research and Innovation Center of Excellence
  • 17:25-18:15: “Demonstration of UAV automated functionalities”
    Mr. Petros Petrides, KIOS Research and Innovation Center of Excellence
  • 18:15-18:30: Coffee break
  • 18:30-18:50: “Regulations on drone aviation in Cyprus”
    Mr. Marios Louka, DJI Cyprus
  • 18:50-19:10: “Monitoring Power Systems Lines using Drones”
    Mr. Costas Stasopoulos, EAC, IEEE Region 8 Past-Director
  • 19:10-19:15: “Contribution of Cyprus Computer Society (CCS) in Cyprus”
    Mr. Costas Agrotis, CCS Chairman
  • 19:15-19.30: “Introduction of IEEE: Its Vision and Role”
    Mr. Nicos Michaelides, CYTA, IEEE Cyprus Section Chair
  • 19:30: Drinks and snacks @ U-Pub – Prize draw for IEEE student members

Flyer (15 downloads)

Program (11 downloads)


Innocence (L’innocence) – William Adolphe Bouguereau (1893)

William-Adolphe Bouguereau’s L’Innocence: Women, young children and lambs are all symbols of innocence.

 

William-Adolphe Bouguereau (November 30, 1825 – August 19, 1905) was a French academic painter and traditionalist. In his realistic genre paintings he used mythological themes, making modern interpretations of classical subjects, with an emphasis on the female human body. During his life he enjoyed significant popularity in France and the United States, was given numerous official honors, and received top prices for his work. As the quintessential salon painter of his generation, he was reviled by the Impressionist avant-garde. By the early twentieth century, Bouguereau and his art fell out of favor with the public, due in part to changing tastes. In the 1980s, a revival of interest in figure painting led to a rediscovery of Bouguereau and his work. Throughout the course of his life, Bouguereau executed 822 known finished paintings, although the whereabouts of many are still unknown.

— From Wikipedia: https://en.wikipedia.org/wiki/William-Adolphe_Bouguereau


CentOS 7: Setup a DHCP server and provide specific IP based on MAC address

Step 1: Install DHCP service

We installed the Dynamic host configuration protocol software (DHCP service) using the command:

yum install dhcp;

The dhcp package provides the ISC DHCP service and relay agent.

Step 2: Configure the DHCP service

Afterwards, we created the file /etc/dhcp/dhcpd.conf using the following content:

subnet 192.168.0.0 netmask 255.255.255.0 {
 option routers                  192.168.0.254;
 option subnet-mask              255.255.255.0;
 option domain-name              "bytefreaks.net";
 option domain-name-servers       192.168.0.1;
 option time-offset              -18000;     # Eastern Standard Time
 range 192.168.0.90 192.168.0.99;
}

host coolServer {
 hardware ethernet 0e:e0:4b:b4:28:82;
 fixed-address 192.168.0.80;
}

This configuration allowed us to provide a DHCP service to the network for the subdomain 192.168.0.x with the range [90,99].
Also, we statically defined the IP for our coolServer using a filter based on the MAC address of the machine.
If you do not want to provide any range, only static IPs, then comment out (#) the line that starts with the word range .

Step 3: Start DHCP service

systemctl start dhcpd.service;

Step 4: Check the status of DHCP service

systemctl status dhcpd.service;

It is a good idea to verify that there are no errors, so be sure to check the status of the service.
You can ignore the error that says “you did not define a subnet declaration for all devices” if you do not really need to do it.

Step 5: Permanently enable the DHCP service

systemctl enable dhcpd.service;

Additional:

Disable the DHCP service

systemctl disable dhcpd.service;

Stop the DHCP service

systemctl stop dhcpd.service;


Bash: After redirected input file is done, allow user to control application via STDIN

Recently, we needed to start an application using a script, which application had its own CLI.
After starting it, we had to feed it with some input to configure it before handing it over to the end user.

The application we used was named dog. We wrote into a plain text file (named food) the commands that we needed to feed the application and then we started the execution using a plain input redirect like so dog < food;.
Doing so, resulted into properly feeding the dog application the food data  but it would cause the application to terminate immediately after the food was done as it would also feed the EOF (End Of File) directive to dog.
Apparently, the application after receiving the EOF, it would then terminate without allowing the end user to take control.

To mitigate the problem, we used the cat command to concatenate the input file along with the stdin stream, permitting us to first feed all the data in the food file and then allow the user to input data using the standard input stream.
Our final command resulted in the following solution as below

cat <(cat food) - | dog;

Where - is the special sign for standard input stdin.
cat food can be of course replaced with other commands that produce output on the standard output (stdout).

A bad side-effect of this solution, is that we lost some functionality of the terminal including, but not limited to, using the backspace and navigation.


Find all git repositories and perform a pull operation on them.

The following command will find all git projects in your home folder and perform a pull operation on them.

find ~ -name ".git" -type d -exec bash -c "echo '{}' && cd '{}'/.. && git pull" \;

The above command is based on finding the .git folders that exist in any clone of a git repository. Once a .git folder is found, it will navigate to its parent folder where it will perform the pull request.

Bonus – Automate the procedure using a cron job

The following entry in crontab allows us to periodically perform a pull request on all the cloned repositories that we have in a specific folder. Specifically, it will perform this operation once every five minutes.

*/5    *    *    *    *    cd /home/bytefreaks/Projects; find . -name ".git" -type d -exec bash -c "echo '{}' && cd '{}'/.. && git pull" \; &> /tmp/bf.git.log

Please note that it would be easier to use an ssh key that does not have a password for this automation.
If you do not, the you will need to either pass the password via this configuration line (not recommended) or have a key agent running to provide the password for the key.

Redirecting standard error (stderr)

The following command will redirect stderr to a different file than the one stdout is redirected to:

command >log.txt 2>errors.txt;

In case you want to redirect stderr to stdout (&1), and then redirect stdout to a file you can use the following setup:

command >mixed-log.txt 2>&1;

The following command will have the same effect as the previous one, the difference between them is the way they are implemented. This time we will redirect both the stdout and stderr to a file:

command &> mixed-log.txt;


Git: fatal: index file smaller than expected

Recently, we got the following error from git

$ git status
 fatal: index file smaller than expected

To fix it, without losing local changes, we removed the corrupted index and reset back to the HEAD using the following commands:

$ rm .git/index
$ git reset HEAD .