Sunday, 24 February 2019

Difference between uint32_t vs unsigned int

Difference between uint32_t vs unsigned int



  • uint32_t is defined in stdint.h header file, so we have to include this header file if we want to use uint32_t
  • It is guaranteed to be a 32-bit unsigned integer
  • unsigned int
    •  Like int, unsigned int typically is an integer that is fast to manipulate for the current architecture
    • so it's to be used when a "normal", fast integer is required.
    •  For example, on a 16 bit-processor unsigned int will typically be 16 bits wide, while uint32_t will have to be 32 bits wide.


Program:

/* Difference between uint32_t vs unsigned int by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */


#include <stdio.h>
#include <stdint.h>  /* For uint32_t */

int main()
{

        /* It is guaranteed to be a 32-bit unsigned integer */
        uint32_t int32_val = 0;
        /* Like int, unsigned int typically is an integer that is fast to manipulate for the current architecture.
         * so it's to be used when a "normal", fast integer is required.
         * For example, on a 16 bit-processor unsigned int will typically be 16 bits wide, while uint32_t
         * will have to be 32 bits wide.
         */
        unsigned int uint_val = 0;

        printf("Vel value int32_val:size <%u:%zu> uint_val:size <%u:%zu> \n", int32_val, sizeof(int32_val), uint_val, sizeof(uint_val));

        return 0;
}



Output:

velraj@velraj-H310M-H:~/velraj/cLang$ ./a.out
Vel value int32_val:size <0:4> uint_val:size <0:4>

Thursday, 17 January 2019

Analysis select timeout, read fd not disturb timeout if tv.sec is not disturbed

SYNOPSIS

       /* According to POSIX.1-2001 */
       #include <sys/select.h>
       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>
       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

Timeout working flow:

  • The select last argument is timeout it receive a struct timeval with second & microsect.
  • The select return is based on below value:
    •  return 0 if timeout happen
    •  return number of FD read if one or multiple FD is ready
    •  return -1 if an error is occured and errno is set.
  • If select is waiting for both read fd & timeout and read fd is ready then select will update the remaining time to the timeout variable.
  • So that next time user should pass the same timeout variable without modify, it will continue the time when it stoped instead of starting fresh.
  • Hence select timeout will be continue paralley, ready FD won't affect the tiemout.

Example:

  • Select is waiting for read fd & timeout for 300 second.
  • 100th second read fd is ready then select return 1 as 1 fd  is ready and remaining second 200 is updated in the timeout variable.
  • After process the read fd call the select timeout without modifiy the remaining timeout.
  • Now select continue the remaining timeout 200 second.
  • 200th second select will be timeout and return 0.
  • Hence Timeout = 300 + time taken by read fd (if few millisecond then its ok).

Note: 

  • The select update the remaining time in the timeout value and start the time after process the FD.
  • The time taken by read FD process is not calculate in  the select timeout, suppose if we use alarm then alarm will run simultaneously and should not face this issue.
  • Suppose read FD is taking more then 1 second and more time then select timeout for 300 second won't be timeout exacatly
  • EG: Timeout = 300 + time taken by read fd (if fd is receiving continuously then problem in timeout).

Server program:

/* Analysis select timeout by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */
#include "stdio.h"
#include "unistd.h"
#include "signal.h"
#include "sys/socket.h"
#include "sys/select.h"
#include "sys/un.h"
#include "string.h"
#include "fcntl.h"
#include <time.h>   /* For localtime */
#define SELECT_TIMEOUT 300
#define TIMESTAMP_BUF_LEN   25
#define TIMESTAMP_FORMAT    "%a %b %d %H:%M:%S %Y"
int get_time_string(char *str_time, unsigned int length, char *time_format)
{
    time_t    time_sec = 0;
    struct tm *time_local = NULL;
    size_t    bytes = 0;
    if ((str_time == NULL) || (time_format == NULL)) {
        printf("Error: The joined time or time format is NULL");
        return 1;
    }
    /* Get value of time in seconds */
    time_sec = time(NULL);
    if (time_sec == -1) {
        printf("Error: Failed to get time in seconds");
        return 2;
    }
    /* Convert a time value to a broken-down local time */
    time_local = localtime(&time_sec);
    if (time_local == NULL) {
        printf("Error: Failed to convert the time value into a broken-down local time");
        return 3;
    }
    /* Format date and time */
    bytes = strftime(str_time, length, time_format, time_local);
    if (bytes == 0) {
        printf("Error: Error in format the data and time");
        return 4;
    }

    return 0;
}
int main() {
    int sock, ret;
    struct sockaddr_un servaddr;
    char buf [20];
    fd_set read_fd_set;
    int fromlen;
    long socketFlags = 0;
    struct timeval timeout;
    char   str_cur_time[TIMESTAMP_BUF_LEN] = {'\0'};
    timeout.tv_sec = SELECT_TIMEOUT;
    timeout.tv_usec = 0;
    // Create Unix domain socket to communicate with client
    if ((sock = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0) {
        perror ("socket failed to open");
        return 1;
    }
    /* Forcefully rebind if already bind and still active.
     * Suppose if already bind and kill the process using ctrl + c, then
     * bind value won't be released by the process. Rebuind will throw error
     * To avoid this error forcefully remove.
     */
    unlink("serversock");
    // Bind socket
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, "serversock");
    if (bind (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
        perror ("socket failed to bind");
        close (sock);
        return 1;
    }
    socketFlags |= O_NONBLOCK;
    if(fcntl(sock, F_SETFL, socketFlags) <0){
        perror ("fcntl failed");
        return 1;
    }
    while (1) {
        FD_ZERO(&read_fd_set);
        FD_SET(sock, &read_fd_set);
        get_time_string(str_cur_time, TIMESTAMP_BUF_LEN, TIMESTAMP_FORMAT);
        printf("\nGoing to select. Will timeout in %d seconds time = %s\r\n", SELECT_TIMEOUT, str_cur_time);
        ret = select (sock + 1, &read_fd_set, NULL, NULL, &timeout);
        printf("Found something\r\n");
        if (ret < 0) { // Error
            perror ("select failed");
            return 1;
        } else if (ret == 0){ // Timeout
            get_time_string(str_cur_time, TIMESTAMP_BUF_LEN, TIMESTAMP_FORMAT);
            printf("Timed out !! current time = %s \r\n", str_cur_time);
            timeout.tv_sec = SELECT_TIMEOUT;
            timeout.tv_usec = 0;
        } else { // Message on FD
           get_time_string(str_cur_time, TIMESTAMP_BUF_LEN, TIMESTAMP_FORMAT);
            printf("FD is read to read so the timeout is tv_sec = %ld tv_usec = %ld time = %s \n", timeout.tv_sec, timeout.tv_usec, str_cur_time);
            if (FD_ISSET(sock, &read_fd_set)){
                printf("FD is set\r\n");
                fromlen = sizeof(servaddr);
                ret = recvfrom(sock, &buf, 20, 0, (struct sockaddr*)&servaddr, (socklen_t*)&fromlen);
                printf("'%s' recieved in buffer of size %d\r\n", buf, ret);
            }
        }
    }
    return 0;
}


Client Program:

/* Analysis select timeout for client by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */
#include "stdio.h"
#include "unistd.h"
#include "signal.h"
#include "sys/socket.h"
#include "sys/select.h"
#include "sys/un.h"
#include "string.h"
int sock;
struct sockaddr_un servaddr;
char buf [20] = "Hello Server";
void sighandler() {
    int len = -1;
    // Doing all this in a sighandler as a test is maybe alright....
    printf("\nSending 'Hello Server' to server from pid %d..\r\n", getpid());
    len = sendto(sock, &buf, 20, 0, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_un));
    if (len < 0) {
        printf("Error. len = %d\r\n", len);
    }
}

int main() {
    struct sigaction new_action, old_action;
    int len = -1;
    // Setting the signal handler
    // Will send a message to server on SIGUSR1
    new_action.sa_handler = sighandler;
    sigemptyset(&new_action.sa_mask);
    new_action.sa_flags = 0;
    sigaction(SIGUSR1, NULL, &old_action);
    if (old_action.sa_handler != SIG_IGN)
        sigaction(SIGUSR1, &new_action, NULL);
    // Create Unix domain socket to communicate with server
    if ((sock = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0) {
        perror ("socket failed to open");
        return 1;
    }
    // Setting server address
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, "serversock");
    while (1) {
        // Do nothing. Just wait for the SIGUSR1 to send a message to server
//    len = sendto(sock, &buf, 20, 0, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_un));
    sleep(1);
    }
    return 0;
}


Output:

Server:
labuser@labuser-virtual-machine:~/velrajk/sample/select$ ./ser
Going to select. Will timeout in 300 seconds time = Thu Jan 17 18:50:18 2019
Found something
FD is read to read so the timeout is tv_sec = 196 tv_usec = 207733 time = Thu Jan 17 18:52:02 2019
FD is set
'Hello Server' recieved in buffer of size 20
Going to select. Will timeout in 300 seconds time = Thu Jan 17 18:52:02 2019
Found something
FD is read to read so the timeout is tv_sec = 120 tv_usec = 832029 time = Thu Jan 17 18:53:17 2019
FD is set
'Hello Server' recieved in buffer of size 20
Going to select. Will timeout in 300 seconds time = Thu Jan 17 18:53:17 2019



Found something
Timed out !! current time = Thu Jan 17 18:55:18 2019
Going to select. Will timeout in 300 seconds time = Thu Jan 17 18:55:18 2019


Client:

labuser@labuser-virtual-machine:~/velrajk/sample/select$ ./a.out
Sending 'Hello Server' to server from pid 11052..
Sending 'Hello Server' to server from pid 11052..

Send signal to client from other console:
ps -aux | grep a.out
kill -s SIGUSR1 <Pid>




Tuesday, 8 January 2019

Instead of print write the data to file with timestamp

 Instead of print write the data to file with timestamp


Program:


/* Instead of print write to file by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>
#include <time.h>  // For time
#include <stdarg.h>  // For va_start

#define TIME_BUF    25
void write_to_default_file(const char *format, ...)
{
    va_list args;
    FILE * fp;
    time_t tim;   // not a primitive datatype
    char str_time[TIME_BUF] = {0};
    struct tm *time_local = NULL;

    fp = fopen ("vel_test.txt", "a+");
    va_start(args, format);
    time(&tim);
    /* Ctime automatically append new line to the output, so we count not use
     * EG: time_str = ctime(&t); // Ctime giving automatically new line, so not using
     */
     // Tue Dec 18 12:01:25 2018
    time_local = localtime(&tim);
    /*
     * A for full weekend, B for Full Month name
     * EG: strftime(s, 100, "%A, %B %d %Y %H:%M:%S", p);
     * a for abbrevated weekend, b for abbreviated month name.
     */
    strftime(str_time, TIME_BUF, "%a %b %d %H:%M:%S %Y", time_local);
    fprintf(fp, "%s:: ", str_time);
    vfprintf(fp, format, args);
    fprintf(fp, "\n");
    va_end(args);
    fclose(fp);
}


int main()
{
    write_to_default_file("Vel test %s = %d ", "id", 100);
}

Output:
labuser@labuser-virtual-machine:~/velrajk/sample$ cat vel_test.txt
Tue Jan 08 21:42:13 2019:: Vel test id = 100
Tue Jan 08 21:42:14 2019:: Vel test id = 100
Tue Jan 08 21:42:14 2019:: Vel test id = 100
labuser@labuser-virtual-machine:~/velrajk/sample$



Friday, 21 December 2018

Convert the string to mac address & hh format specifier


  • Use hh format specifier to convert the string into a MAC address.



int sscanf(const char *str, const char *format, ...)

Description:


  hh              Specifies that a following d, i, o, u, x, or  X
                    conversion  specifier  applies to a signed char
                    or unsigned char argument  (the  argument  will
                    have  been  promoted  according  to the integer
                    promotions, but its value shall be converted to
                    signed  char or unsigned char before printing);
                    or that  a  following  n  conversion  specifier
                    applies to a pointer to a signed char argument.


Table


ModifierModifiesApplies to
hhd, i, o, u, x, or Xchar, signed char or unsigned char
hd, i, o, u, x, or Xshort int or unsigned short int



Format specifierDescriptionSupported data types
%cCharacterchar
unsigned char
%nPrints nothing
%%Prints % character
 specifiers
lengthd iu o x Xf F e E g G a Acspn
(none)intunsigned intdoubleintchar*void*int*
hhsigned charunsigned char    signed char*
hshort intunsigned short int    short int*
llong intunsigned long int wint_twchar_t* long int*
lllong long intunsigned long long int    long long int*
jintmax_tuintmax_t    intmax_t*
zsize_tsize_t    size_t*
tptrdiff_tptrdiff_t    ptrdiff_t*
L  long double    



Program:


/* Convert the string to mac address & hh format specifier by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>
#include <stdint.h>

#define MAC_LEN   6
#define MAC_STR_BUF_LEN 32

#define MAC_INDEX_0 0
#define MAC_INDEX_1 1
#define MAC_INDEX_2 2
#define MAC_INDEX_3 3
#define MAC_INDEX_4 4
#define MAC_INDEX_5 5

typedef uint8_t    tMacAddr[MAC_LEN];

int convert_string_to_mac_address(const char *str_mac, tMacAddr mac_addr, int pattern)
{
    int  ret = 0;
    char *format = NULL;
    char str_mac_buf[MAC_STR_BUF_LEN] = {'\0'};

    switch (pattern) {
        case 0:
            format = "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx";
        break;

        case 1:
            format = "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx";
        break;

        default:
            printf("Pattern for MAC is invalid <%d> \n", pattern);
            return 0;
        break;
    }

    /* Convert the mac MAC address from string */
    ret = sscanf(str_mac, format, &mac_addr[MAC_INDEX_0], &mac_addr[MAC_INDEX_1], &mac_addr[MAC_INDEX_2],
                 &mac_addr[MAC_INDEX_3], &mac_addr[MAC_INDEX_4], &mac_addr[MAC_INDEX_5]);
    if (ret != MAC_LEN) {
        snprintf(str_mac_buf, sizeof(str_mac_buf), format,  mac_addr[MAC_INDEX_0], mac_addr[MAC_INDEX_1],
                 mac_addr[MAC_INDEX_2], mac_addr[MAC_INDEX_3], mac_addr[MAC_INDEX_4], mac_addr[MAC_INDEX_5]);
        printf("Error in converting the mac from string %s ret <%d>", str_mac_buf, ret);
        return 0;
    }

    return 0;
}


int main()
{
    tMacAddr mac1 = {0}, mac_no_colon = {0};

    convert_string_to_mac_address("00:0c:29:44:00:d3", mac1, 0);

    printf("Converted mac is <MAC:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx> \n", mac1[MAC_INDEX_0], mac1[MAC_INDEX_1], mac1[MAC_INDEX_2],
            mac1[MAC_INDEX_3], mac1[MAC_INDEX_4], mac1[MAC_INDEX_5]);


    convert_string_to_mac_address("000c294402d4", mac_no_colon, 1);
    printf("Converted mac is <MAC:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx> \n", mac_no_colon[MAC_INDEX_0], mac_no_colon[MAC_INDEX_1], mac_no_colon[MAC_INDEX_2],
            mac_no_colon[MAC_INDEX_3], mac_no_colon[MAC_INDEX_4], mac_no_colon[MAC_INDEX_5]);
    return 0;
}



  Output:

  $/sample$ ./a.out
  Converted mac is <MAC:00:0c:29:44:00:d3>
  Converted mac is <MAC:00:0c:29:44:02:d4>

Sizeof format zu or u

Sizeof format zu or u



  • It is a compile time unary operator which can be used to compute the size of its operand.
  • The result of sizeof is of unsigned integral type which is usually denoted by size_t.
  • sizeof can be applied to any data-type, including primitive types such as integer and floating-point types, pointer types, or compound datatypes such as Structure, union etc.
  • It simply return amount of memory is allocated to that data types.

 

Program:


/* sizeof by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>
 

#define STRNAME "Velraj"

int main()
{
        printf("Vel size = %zu int= %zu float = %zu double= %zu 0 = %zu NULL = %zu  \"\" = %zu int * = %zu\n",
                sizeof("vel"), sizeof(int), sizeof(float), sizeof(double), sizeof(0), sizeof(NULL), sizeof(""), sizeof(int *));

        return 0;
}

Output:

   velrajk/sample$ ./a.out
   Vel size = 4 int= 4 float = 4 double= 8 0 = 4 NULL = 8  "" = 1 int * = 8

Sunday, 11 November 2018

static use on other file compile together throws error

Static file:


  • Even if we give 2 .c file into the gcc, it will compile upto Assembler as a single .c file.
  • The below output shows that Preprocessor gave .i for 2 files.
    • Compiler gave the .s for 2 files.
    • Assembler gave the .o for 2 fileHence linker only combine these 2 .o files into a single executable file.
    • Hence we could not use the static variable in other .c file because each .c file compile separately upto .o
    • NO_STAT flag is used to remove the extern on 2nd file and make an global variable,
      • so that 2 variable are different variable even with the same name.
  • ------------ snip ---------------
  •  -r-- 1 manirathinam manirathinam   197 Nov 11 03:28 static_1.c
    -rw-rw-r-- 1 manirathinam manirathinam   171 Nov 11 03:30 static_2.c
    -rw-rw-r-- 1 manirathinam manirathinam 18382 Nov 11 03:30 static_1.i
    -rw-rw-r-- 1 manirathinam manirathinam  1174 Nov 11 03:30 static_1.s
    -rw-rw-r-- 1 manirathinam manirathinam  1392 Nov 11 03:30 static_1.o
    -rw-rw-r-- 1 manirathinam manirathinam 18398 Nov 11 03:30 static_2.i
    -rw-rw-r-- 1 manirathinam manirathinam   853 Nov 11 03:30 static_2.s
    -rw-rw-r-- 1 manirathinam manirathinam  1244 Nov 11 03:30 static_2.o
    -rwxrwxr-x 1 manirathinam manirathinam  7312 Nov 11 03:30 a.out
    manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
  •  
  • ---------------- snip --------------


Program:

File 1: static_1.c


/* static on 2 file compile together by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>

static int stat_value = 0;
// we can inclide the .c file it can able to compile successfuly.
//#include "static_2.c"



int main()
{
        printf("Inside main \n");

        return 0;
}


/* Compile :
 * Gcc working for 2 .c file:
 *     Even if we give 2 .c file into the gcc, it will compile upto Assembler as a single .c file.
 *     The below output shows that Preprocessor gave .i for 2 files.
 *                                 Compiler gave the .s for 2 files.
 *                                 Assembler gave the .o for 2 files
 *                                 Hence linker only combine these 2 .o files into a single executable file.
 *                   Hence we could not use the static variable in other .c file because each .c file compile separately upto .o
 *                   NO_STAT flag is used to remove the extern on 2nd file and make an global variable,
 *                       so that 2 variable are different variable even with the same name.
 *
 manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ ls -ltr
total 16
-rw-rw-r-- 1 manirathinam manirathinam  197 Nov 11 03:28 static_1.c
-rw-rw-r-- 1 manirathinam manirathinam  171 Nov 11 03:30 static_2.c
-rwxrwxr-x 1 manirathinam manirathinam 7312 Nov 11 03:30 a.out
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ gcc static_1.c static_2.c --save-temp
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$  ls -ltr
total 72
-rw-rw-r-- 1 manirathinam manirathinam   197 Nov 11 03:28 static_1.c
-rw-rw-r-- 1 manirathinam manirathinam   171 Nov 11 03:30 static_2.c
-rw-rw-r-- 1 manirathinam manirathinam 18382 Nov 11 03:30 static_1.i
-rw-rw-r-- 1 manirathinam manirathinam  1174 Nov 11 03:30 static_1.s
-rw-rw-r-- 1 manirathinam manirathinam  1392 Nov 11 03:30 static_1.o
-rw-rw-r-- 1 manirathinam manirathinam 18398 Nov 11 03:30 static_2.i
-rw-rw-r-- 1 manirathinam manirathinam   853 Nov 11 03:30 static_2.s
-rw-rw-r-- 1 manirathinam manirathinam  1244 Nov 11 03:30 static_2.o
-rwxrwxr-x 1 manirathinam manirathinam  7312 Nov 11 03:30 a.out
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ gcc static_1.c static_2.c --save-temp -DNO_STAT
static_2.o: In function `add':
static_2.c:(.text+0x19): undefined reference to `stat_value'
collect2: error: ld returned 1 exit status
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
*/


File 2: static_2.c


/* static on 2 file compile together by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>


#ifdef NO_STAT
extern int stat_value;
#else
int stat_value;
#endif


int add()
{
        int value = 100;
        value = stat_value + value;

        return value;
}

Friday, 9 November 2018

pthread mutux deadlock for cancel handling




Program:

// C program to demonstrates cancellation of self thread
// using thread id
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>  // For memset
static pthread_mutex_t cfglock = PTHREAD_MUTEX_INITIALIZER;
int is_thread_cancel = 0, is_cleanup_push = 0;
void line_80(char ch)
{
    char str[81] = {'\0'};
    memset(str, ch, sizeof(str));
    str[80] = '\0';
    printf("%s\n", str);
    return;
}
void *calls(void* ptr)
{
    int oldtype = 0;
    printf("\nThread: Entrying into the thread %s \n", __func__);
    line_80('-');

    /* If 2 argument try then do the clean up */
    /* Add setcanceltype & cleanup into the if loop throws below error:
           error: expected ‘while’ before ‘printf’
       Reason is pthread_cleanup_push is not a function, it is a macro it cotain the below.
       So it add the d0 { on start and pthread_cleanup_pop macro contain ending while, so we could not put inside the if condition
             if (is_cleanup_push) {
     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
     do { __pthread_unwind_buf_t __cancel_buf; void (*__cancel_routine) (void *) = (pthread_mutex_unlock); void *__cancel_arg = ((void *) &cfglock); int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect ((__not_first_call), 0)) { __cancel_routine (__cancel_arg); __pthread_unwind_next (&__cancel_buf); } __pthread_register_cancel (&__cancel_buf); do {;
        }
        pthread_cleanup_pop macro definition is:
        do { } while (0); } while (0); __pthread_unregister_cancel (&__cancel_buf); if (0) __cancel_routine (__cancel_arg); } while (0);
         pthread_setcanceltype(oldtype, ((void *)0));

      */
 //  if (is_cleanup_push) {
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
        pthread_cleanup_push(pthread_mutex_unlock, (void *) &cfglock);
  //  }
    printf("Thread: Going to accquire the lock\n");
    pthread_mutex_lock(&cfglock);
    printf("Thread: Lock is accquired \n");
    printf("Thread: Going to sleep 10 second \n");
    sleep(7);
    printf("Thread: After the sleep of 10 second\n");
    /* If 2 argument try then do the clean up */
  //  if (is_cleanup_push) {
        pthread_mutex_unlock(&cfglock);
        pthread_cleanup_pop(0);
        pthread_setcanceltype(oldtype, NULL);
    //}
    printf("\nThread: Returning from thread %s \n", __func__);
    line_80('-');
    return NULL;
}

int main(int argc, char *argv[])
{
    // NULL when no attribute
    pthread_t thread = 0;
    int ret = 0;
    void *thread_ret = NULL;
    // calls is a function name
    pthread_create(&thread, NULL, calls, NULL);
    /* Argument and his valuel
          Arg 1. if 0 then no cancel, if 1 then it will call pthread_cancel.
                     Scenario: if 0 then, no cancel, thread in lock, process also try to lock, Dead lock
                     scenario 2: if 1 then , cancel kill the thread but lock is not cleaned, so proacess try to lock, hence Dead lock.
          Arg  2. if 0 then no cleanup_push for lock,
                  if 1 then do cleanup_push for lock

      */
    printf("Process: going to sleep for 3  \n");
    sleep(3);
    printf("\t\tProcess: After sleep of 3 second  \n");
    is_thread_cancel = atoi(argv[1]);
    is_cleanup_push = atoi(argv[2]);
    if (is_thread_cancel == 1) {
        /* cancelled threads do not unlock mutexes they hold */
        printf("Process: called the pthread_cancel \n");
        ret = pthread_cancel(thread);
        if (ret == 0) {
            printf("Process: Canceled the thread with ID <%ld> \n", thread);
        } else {
            printf("Process: Error in cancel while try to cancel the thread <%ld>, ret = %d \n",
                    thread, ret);
        }
    }
  //  printf("After cancel \n");

    /* Already taken the lock in thread, so this lock will be blocked */
    printf("Process: Going to acquire the Mutux  \n");
    pthread_mutex_lock(&cfglock);
    printf("\t\tProcess: Lock is acquired \n");
    pthread_mutex_unlock(&cfglock);
    printf("\t\tProcess: Mutux lock is released \n");
    printf("Process: going to sleep for 15  \n");
    sleep(10);
    printf("\t\tProcess: After sleep of 15 second  \n");
    /* The pthread_join() function waits for the thread specified by thread to terminate.
     * If that thread has already terminated, then pthread_join() returns immediately.
     * If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.
     * As per out PTHREAD_CANCELED value is 0xfffff
       */
    // Waiting for when thread is completed
//    ret = pthread_join(thread, NULL);  // Just  wati
    ret = pthread_join(thread, &thread_ret);  // Just  wati
    if (ret !=0) {
        printf("Process: Error in pthread_join errno = %d \n", ret);
    }
    printf("Process: The return value from thread is = %p \n", thread_ret);
    if (thread_ret == PTHREAD_CANCELED) {
        printf("Process: The thread is already canceled, value of PTHREAD_CANCELED  <%p>\n", PTHREAD_CANCELED);
    }
    return 0;
}

/* Ref:
        For Dedlock release lock, Solution:
                https://stackoverflow.com/questions/14268080/cancelling-a-thread-that-has-a-mutex-locked-does-not-unlock-the-mutex
       Solution method 2: For pthread_mutexattr_setrobust to releace lock:
               http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html
               https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization
        Solution Method 1:
               https://sector7.xray.aps.anl.gov/~dohnarms/programming/glibc/html/Cleanup-Handlers.html
               https://linux.die.net/man/3/pthread_cleanup_push
*/