Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8937507
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T10:25:43+00:00 2026-06-15T10:25:43+00:00

I am busy with a project where I have to automate some processes in

  • 0

I am busy with a project where I have to automate some processes in bash or ssh so I decided to use the libexpect.so library. If you don’t know what libexpect is, it provides an expect extension that I can use in a c++ program, and expect is just a program where you can run automated scripts for things like ssh. So I can execute a script which attempts to ssh somewhere…when the password prompt is found by expect I could have already given expect a password to send.

My problem is that when I run a program, even a really simple one, I get a segmentation fault which I narrowed down, with gdb, to a function in libexpect.so called exp_spawnv.

I know I’ve linked the library right, it compiles fine and infact the whole problem doesn’t exist when I compile and run in ubuntu, but in my arch linux install I get the segmentation fault which I’ll detail later. The reason why I’m building it on arch is because I want to eventually make the project buildable on most distros.

My thoughts are that in my arch installation there are permissions which fail when the exp_spawnv function is called, perhaps a pipe, fork or whatever.

To prove that I’m not doing something funky, here is a simple main.cpp for illustration purposes.

#include <tcl8.5/expect.h>

int main()
{
  FILE* file = exp_popen("bash");
}

So it is just about the most simple expect program ever made. Here is me compiling and linking it.

$ g++ -ggdb -c main.cpp

main.cpp: In function ‘int main()’:

main.cpp:5:32: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

$ g++ main.o -lexpect -o mainprog

So I got my executable mainprog…just running that will give me a segmentation fault and nothing else.

If I run mainprog in gdb it tells me that there is a seg fault in exp_spawnv. Here is what I did in gdb with the backtrace at the end.

(gdb) run

Starting program: /home/user/testlibexpect/mainprog

warning: Could not load shared library symbols for linux-vdso.so.1.

Do you need “set solib-search-path” or “set sysroot”?

Program received signal SIGSEGV, Segmentation fault.

0x00007ffff7bc8836 in exp_spawnv () from /usr/lib/libexpect.so

(gdb) backtrace

0 0x00007ffff7bc8836 in exp_spawnv () from /usr/lib/libexpect.so

1 0x00007ffff7bc8cb4 in exp_spawnl () from /usr/lib/libexpect.so

2 0x00007ffff7bc8d01 in exp_popen () from /usr/lib/libexpect.so

3 0x000000000040069e in main () at main.cpp:5

Two things concern me.

  1. looking at the manpage for libexpect, I know exp_spawnv forks a new process and I’ll be able to communicate through the FILE*. So I guess that SIGSEGV signal is received because something bad has happened with the fork?

  2. That line (warning: Could not load shared library symbols for linux-vdso.so.1.) in the backtrace looks fishy?

So in summary, my question is what should I look into to fix this problem? I have tried building the expect library from source and by acquiring it with the arch package manager pacman…the problem persists so I don’t think the library build is corrupt if you know what I mean.

EDIT: point 2 of my concerns is not a problem according to research I’ve done, just cosmetic.

The disassembly from eclipse is below:

00007ffff7bc87c6:   mov 0x20c68b(%rip),%rax        # 0x7ffff7dd4e58
00007ffff7bc87cd:   mov (%rax),%rax
00007ffff7bc87d0:   test %rax,%rax
00007ffff7bc87d3:   je 0x7ffff7bc87d7 <exp_spawnv+935>
00007ffff7bc87d5:   callq *%rax
00007ffff7bc87d7:   mov %r12,%rsi
00007ffff7bc87da:   mov %rbp,%rdi
00007ffff7bc87dd:   callq 0x7ffff7bb2330 <execvp@plt>
00007ffff7bc87e2:   callq 0x7ffff7bb1720 <__errno_location@plt>
00007ffff7bc87e7:   mov 0x24(%rsp),%edi
00007ffff7bc87eb:   mov %rax,%rsi
00007ffff7bc87ee:   mov $0x4,%edx
00007ffff7bc87f3:   xor %eax,%eax
00007ffff7bc87f5:   callq 0x7ffff7bb1910 <write@plt>
00007ffff7bc87fa:   mov $0xffffffff,%edi
00007ffff7bc87ff:   callq 0x7ffff7bb23d0 <exit@plt>
00007ffff7bc8804:   nopl 0x0(%rax)
00007ffff7bc8808:   xor %eax,%eax
00007ffff7bc880a:   movl $0x0,0x20dd3c(%rip)        # 0x7ffff7dd6550
00007ffff7bc8814:   callq 0x7ffff7bb1700 <exp_init_pty@plt>
00007ffff7bc8819:   xor %eax,%eax
00007ffff7bc881b:   callq 0x7ffff7bb2460 <exp_init_tty@plt>
00007ffff7bc8820:   lea -0x1c97(%rip),%rdi        # 0x7ffff7bc6b90
00007ffff7bc8827:   callq 0x7ffff7bb2540 <expDiagLogPtrSet@plt>
00007ffff7bc882c:   mov 0x20c555(%rip),%rax        # 0x7ffff7dd4d88
00007ffff7bc8833:   mov (%rax),%rax
00007ffff7bc8836:   mov 0x410(%rax),%rdi

THE ANSWER I CAME UP WITH

Here is the solution I eventually came up with, I have accepted szx’s answer because it lead me down this path which was trivial once I knew what I was looking for.

//do not use TCL stubs as this is a main
#undef USE_TCL_STUBS


#include <iostream>
using std::cout;
using std::endl;

//headers that must be included when using expectTcl as an extension to c++ program
#include <stdio.h>
#include <stdlib.h>
#include <expectTcl/tcl.h>
#include <expectTcl/expect_tcl.h>
#include <expectTcl/expect.h>

//enums representing cases of what expect found in loop
enum{FOUNDSEARCH, PROMPT};

int main()
{
  /* initialise expect and tcl */
  Tcl_Interp *interp = Tcl_CreateInterp();

  if(Tcl_Init(interp) == TCL_ERROR)
    {
      cout << "TCL failed to initialize." << endl;
    }
  if(Expect_Init(interp) == TCL_ERROR)
    {
      cout << "Expect failed to initialize." << endl;
    }

  /* end of intialisation procedure */

  //open a shell with a pipe
  char shellType[] = "sh";
  FILE* fp = exp_popen(shellType);

  //should we exit from the loop which is studying sh output
  bool shouldBreak = false;
  //did we find the pwd
  bool foundSearch = false;
  //does it look like expect is working
  bool expectWorking = false;
  //did we receive a prompt...therefore we should send a command
  bool receivedPrompt = false;

  while(shouldBreak == false)
    {
      switch(exp_fexpectl(fp,
              exp_glob, "/tools/test*", FOUNDSEARCH,  //different
              exp_glob,"# ", PROMPT, //cases are shown here
              exp_end))  //that the expect loop could encounter
    {
    case FOUNDSEARCH:
      foundSearch = true;
      break;
    case PROMPT:
      if (receivedPrompt)
        {
          shouldBreak = true;
          expectWorking = true;
        }
      else
        {
          receivedPrompt = true;
          fprintf(fp, "%s\r", "pwd");
        }
      break;
    case EXP_TIMEOUT:
      shouldBreak = true;
      break;
    case EXP_EOF:
      shouldBreak = true;
      break;
    }

      //cout << "exp_match : " << exp_match << endl;
    }

  cout << endl;
  if (foundSearch)
    {
      cout << "Expect found output of pwd" << endl;
    }
  else
    {
      cout << "Expect failed to find output of pwd" << endl;
    }
  if(expectWorking)
    {
      cout << "The expect interface is working" << endl;
    }
  else
    {
      cout << "The expect interface is not working" << endl;
    }


  cout << "The test program successfully reached the end" << endl;
}

All I’ve done here is shown how to initialize expect/tcl to prevent the problem I had that szx was talking about. Then I just did a typical expect like problem where I pretty much said if the shell prompts you for input send it pwd. Then, if it gives you the current directory expect is working. This kind of structure can be extremely useful for something like ssh. Say if you want to automate sshing somewhere, doing something and then getting out of there. Especially if you want to do it a couple hundred times and you don’t want to confirm the authenticity of every host and type a password in every time.

Note that I never had to do this on ubuntu for some reason…possibly because I did not build it from source and just used apt-get. However, my project requires me to build from source so I found a really good, neat way to do it on http://www.linuxfromscratch.org/lfs/view/development/chapter05/tcl.html and http://www.linuxfromscratch.org/lfs/view/development/chapter05/expect.html… infact that whole website looks really useful.

Thanks again to szx

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T10:25:44+00:00Added an answer on June 15, 2026 at 10:25 am

    The global variable TclStubs *tclStubsPtr defined inside Tcl happens to be NULL when exp_spawnv tries to accessTcl_ErrnoMsg which is defined as a member of that structure (see tcl.h):

    #ifndef Tcl_ErrnoMsg
    #define Tcl_ErrnoMsg \
        (tclStubsPtr->tcl_ErrnoMsg) /* 128 */
    #endif
    

    I’m not familiar with neither expect nor Tcl but the above suggests that you probably should call some initialization subroutine (if there exists one) or set it manually.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm busy on a project and I have some extra javascript files that need
I have been busy in my project creating a webapp (in struts) that manages
i'm busy with a school project and I have to build a web app.
I am busy with a new project based on zend framework. I have created
I am busy with a project and want to know what is Generic iterator
Currently I'm busy on a project using XML messaging. I have one general schema,
I am busy with an MVC 2 project. I have my entity framework 4
I need some help with setting up a spring project. I am busy going
Im busy with my app and i walked in some problems when i click
I'm busy with a website and for an element I use preg_replace to replace

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.