0

In the following code:

FILE *cmd = popen("pidof -s gst-launch-0.10", "r");

Where will the String "pidof -s gst-launch-0.10" stored in the Process address space. I don't see it in the Stack..

Adding the whole code:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0

#define VS_STREAMER_ON      1
#define VS_STREAMER_OFF     2
#define VS_VIDSIG_ON        3
#define VS_VIDSIG_OFF       4
#define VS_VSIG_BL_OFF      5


typedef int bool;
bool bVidSignal, bVidSignalOld = FALSE;
int iVidState = VS_STREAMER_OFF;


bool IsStreamerRunning();

bool stopStreamer();
bool startStreamer();

bool ShowNoSignal()
{
    printf("\nShowNoSignal()\n");

    system("dd if=/home/TDS/DiskOnChip/nosig.bmp of=/dev/fb0");

    return TRUE;
}


bool GetVideoSignal()
{

    char buffer[10];

    memset(buffer, '\0', 10);

    int fd = open("/sys/bus/i2c/devices/1-000f/sysstatus", O_RDONLY, 0);
    //int fd = open("/sys/bus/i2c/drivers/tc358743_mipi/1-000f/sysstatus", O_RDONLY, 0);

    if (fd > 0)
    {
        read(fd, buffer, sizeof(buffer));

        if (strlen(buffer) > 0)
        {
            long val = strtoul(buffer, NULL, 16);

            close(fd);

            if (val == 0x8F)
            {

                return TRUE;
            }
            else
            {

                return FALSE;
            }
        }
    }
    else
    {
        printf("GetVideoSignal(): can't open file\n");
    }


    return FALSE;

}




void CheckVideoState(void)
{
    //static int iRestartCnt = 0;
    static int iAppCheckTic = 60;                           // To Run for the first time
    static int iVideoOn = FALSE;
    static int iGstreamerStartCount = 0;
    static int iGstreamerStartAttempt = 0;
    static int iGstreamerStopCounter = 0;

    bVidSignal = GetVideoSignal();

    if ( (bVidSignal) && (bVidSignalOld) )
    {
        iVideoOn = TRUE;
        printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
    }

    else if ( (!bVidSignal) && (!bVidSignalOld) )
    {
        iVideoOn = FALSE;
        printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
    }
    else
    {
        printf("CheckVideoState() VideoOn=%d, MIPI_Status=%d, MIPI_Last_Status=%d\n",iVideoOn, bVidSignal, bVidSignalOld);
    }
    bVidSignalOld = bVidSignal;

    switch (iVidState)
    {
        case VS_STREAMER_OFF:

            if ( iVideoOn )
            {
                iGstreamerStartCount = 0;
                iGstreamerStartAttempt = 0;
                printf("CheckVideoState():VS_STREAMER_OFF:  Signal ON\n");

        iVidState = VS_VIDSIG_ON;
            }
            else
            {
                iAppCheckTic++;
                if ( iAppCheckTic >= 60 )
                {
                    iAppCheckTic = 0;
                    iGstreamerStartCount = 0;
                    iGstreamerStartAttempt = 0;
                    if ( IsStreamerRunning() )
                    {
                        printf("CheckVideoState():VS_STREAMER_OFF:  Killing Gstreamer\n");
                        stopStreamer();
                        sleep(1);
                        ShowNoSignal();
                    }
                }
            }
            break;


       case VS_VIDSIG_ON:

            if ( iGstreamerStartAttempt > 5 )
            {
                printf("CheckVideoState():calling Reboot after 5 Gstreamer Restarts!\n");
                //SystemExit(SS_REBOOT);
        system("reboot");
            }

            if ( iGstreamerStartCount ==  0 )
            {
                if ( IsStreamerRunning() )
                {
                    iGstreamerStopCounter = 0;
                    iVidState = VS_VIDSIG_OFF;
                    printf("CheckVideoState():VS_VIDSIG_ON:   GStreamer Running Already Switch to VS_VIDSIG_OFF\n");
                }
                else
                {
                    startStreamer();
                    printf("CheckVideoState():VS_VIDSIG_ON:   Starting GStreamer\n");
                    iGstreamerStartCount++;
                    iGstreamerStartAttempt++;
                }
            }
            if ( iGstreamerStartCount >= 10 )
            {
                if ( IsStreamerRunning() )
                {
                    iVidState = VS_STREAMER_ON;
                    printf("CheckVideoState(): VS_VIDSIG_ON:   GStreamer Running After %d Seconds,  Switching to VS_STREAMER_ON\n", iGstreamerStartCount);
                }
        else
                {
                    iGstreamerStartCount = 0;
                    printf("CheckVideoState(): VS_VIDSIG_ON:   GStreamer Not Running After 5 Seconds,  Clearing iGstreamerStartCount\n");
                }
                break;
            }
            iGstreamerStartCount++;
            break;

        case VS_STREAMER_ON:
            if ( iVideoOn )
            {
                if ( !IsStreamerRunning() )
                {
                    iGstreamerStartCount = 0;
                    iGstreamerStartAttempt = 0;
                    printf("CheckVideoState():VS_STREAMER_ON:  Gstreamer Not running even after video signal available\n");
                }
            }
        else
            {
                iVidState = VS_VIDSIG_OFF;
                printf("CheckVideoState():VS_STREAMER_ON: Lost Video Signal\n");
                iGstreamerStopCounter = 0;
            }
            break;

        case VS_VIDSIG_OFF:

            if ( IsStreamerRunning() )
            {
                stopStreamer();
                printf("CheckVideoState():VS_VIDSIG_OFF:  Killing GStreamer\n");

            }
            else
            {
                if ( iGstreamerStopCounter >= 3 )
                {
                    iVidState = VS_STREAMER_OFF;
                    printf("CheckVideoState():VS_VIDSIG_OFF:  Switching to VS_STREAMER_OFF after 3 seconds\n");
                    break;
                }
            }
            iGstreamerStopCounter++;
            break;
    }
}


pid_t GetStreamerPID()
{
    pid_t pid = 0;

    char line[100];

    memset(line, '\0', 100);

    FILE *cmd = popen("pidof -s gst-launch-0.10", "r");

    if ( cmd == NULL )
    {
    printf("Cmd Null\n");
    }    
    fgets(line, 100, cmd);

    if (strlen(line) > 0)
    {
        pid = strtoul(line, NULL, 10);
    }

    pclose(cmd);    
    return pid;
}


bool IsStreamerRunning()
{
    pid_t pid = GetStreamerPID();

    if (pid > 0)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


void MainLoop()
{
    while(1)
    {

        sleep(1);       
        CheckVideoState();

    }

}

bool startStreamer()
{
    char command[256];

    pid_t pid = GetStreamerPID();

    if (pid > 0)
    {
    }
    else
    {

        sprintf(command, "gst-launch imxv4l2src ! imxv4l2sink &");

        printf("StartStreamer: command=[%s]\n", command);

        system(command);
    }
    return TRUE;
}

bool stopStreamer()
{
    char command[256];

    pid_t pid = GetStreamerPID();

    if (pid > 0)
    {

        sprintf(command, "kill %d", pid);

        printf("StopStreamer: command=[%s]\n", command);

        system(command);
    }
    else
    {
    }

    return TRUE;

}




int main()
{

    MainLoop();
    return 0;
}

The code is crashing with Segmentation Fault and that is happening at IsStreamerRunning() function at CheckVideoState() Case VS_VIDSIG_ON...Note. This happens randomly.. Debugging through gdb, the backtrace stopped at popen and it was accessing the memory which is not permitted to access. Hence segmentation Fault. Can anyone help me out..

Adding gdb backtrace:

Breakpoint 1, 0x76ea6ffc in popen@@GLIBC_2.4 () from /lib/libc.so.6
#0  0x76ea6ffc in popen@@GLIBC_2.4 () from /lib/libc.so.6
#1  0x00010d14 in GetStreamerPID () at getPid.c:243
#2  0x00010d98 in IsStreamerRunning () at getPid.c:263
#3  0x00010aac in CheckVideoState () at getPid.c:157
#4  0x00010dd4 in MainLoop () at getPid.c:284
#5  0x00010efc in main () at getPid.c:358

Program received signal SIGSEGV, Segmentation fault.
0x80808080 in ?? ()

(gdb) bt
#0  0x80808080 in ?? ()
#1  0x76ee1b70 in fork () from /lib/libc.so.6
#2  0x76ea6d80 in _IO_proc_open@@GLIBC_2.4 () from /lib/libc.so.6
#3  0x76ea704c in popen@@GLIBC_2.4 () from /lib/libc.so.6
#4  0x00010d14 in GetStreamerPID () at getPid.c:243
#5  0x00010d98 in IsStreamerRunning () at getPid.c:263
#6  0x00010aac in CheckVideoState () at getPid.c:157
#7  0x00010dd4 in MainLoop () at getPid.c:284
#8  0x00010efc in main () at getPid.c:358

I am debugging from the past week, using valgrind, gdb , I have no idea why it is going accessing address out of the memory

md.jamal
  • 4,067
  • 8
  • 45
  • 108
  • When you say *the* process address space, to which process are you referring? The parent or child? – Jonathon Reinhart May 05 '17 at 10:39
  • Rather than define `line` and assign afterwards, you can initialize at definition: `char line[100] = {0};`. – pmg May 05 '17 at 10:40
  • parent... I am facing a wierd problem with this function.. It is randomly throwing segmentation fault at popen...Can anybody guess what can be the issue.. – md.jamal May 05 '17 at 10:41
  • 1
    @pmg Your solution and the OP's current code fill all 100 bytes with zeros. But, there's no point in doing so because the OP proceeds to tell fgets() to overwrite the buffer. If you want to be "safe" (because you are too lazy to check the return value of fgets), you need only to write a single NUL terminator: `line[0] = '\0';` – Jonathon Reinhart May 05 '17 at 10:44
  • Hi Jonathon.. I have added my whole code, which crashes randomly by throwing segmentation fault.. And this happens when it is calling popen API from IsStreamerRunning().. Also this only happens randomly when it is in the VS_VIDSIG_ON case – md.jamal May 05 '17 at 10:50

2 Answers2

0

The content of both "pidof -s gst-launch-0.10" and "r" strings is stored in implementation-defined area. It is common to place string literals in the "text" area with the code, or in the read-only the data section.

What gets on the stack in the process of passing parameters to the function is two addresses of these string literals, not their content. That is why you are unable to find the strings in the space of your process stack.

See this Q&A for more information on string literal placement in memory.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Popen is a high-level API that will do the following (on a POSIX platformĺ:

  • Parse your string per shell semantics and construct an "argv" array
  • Open pipes for stdin, stdout, stderr of the new process
  • Fork
  • Dup2 the pipes to the appropriate file descriptors
  • Exec the new process

So your string in question won't be present, per se, in the new process address space. Rather the components of it will be present in the passed argv.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328