libcurl, always segmentation violation

Linux specific forum
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

libcurl, always segmentation violation

Post by Deluxe0321 »

Hi,
I want to create a little application using the curl library.
Sadly I have not been able to get it working - still the same issue I had last year (viewtopic.php?f=13&t=41482).
This time I did even a fresh debian squeeze (amd64) install on my pc, simply to make sure this is not a configuration issue.
The curl-ssl library has been updated since my last test, the issue still remains.
I thought first, well then import the library by using Import(C), again the same damn issue. I ended up by using the "classic GetFunction() way" --> the same again...

Curl itself is working perfectly - I can't explain it to myself, am I missing something?

Test Code:

Code: Select all

;PB 5.10b3. 
;curltest
Procedure ErrorHandler()
 
  ErrorMessage$ = "A program error was detected:" + #CRLF$ 
  ErrorMessage$ + #CRLF$
  ErrorMessage$ + "Error Message:   " + ErrorMessage()      + #CRLF$
  ErrorMessage$ + "Error Code:      " + Str(ErrorCode())    + #CRLF$  
  ErrorMessage$ + "Code Address:    " + Str(ErrorAddress()) + #CRLF$
 
  If ErrorCode() = #PB_OnError_InvalidMemory   
    ErrorMessage$ + "Target Address:  " + Str(ErrorTargetAddress()) + #CRLF$
  EndIf
 
  If ErrorLine() = -1
    ErrorMessage$ + "Sourcecode line: Enable OnError lines support to get code line information." + #CRLF$
  Else
    ErrorMessage$ + "Sourcecode line: " + Str(ErrorLine()) + #CRLF$
    ErrorMessage$ + "Sourcecode file: " + ErrorFile() + #CRLF$
  EndIf
 
  ErrorMessage$ + #CRLF$
  ErrorMessage$ + "Register content:" + #CRLF$
      ErrorMessage$ + "RAX = " + Str(ErrorRegister(#PB_OnError_RAX)) + #CRLF$
      ErrorMessage$ + "RBX = " + Str(ErrorRegister(#PB_OnError_RBX)) + #CRLF$
      ErrorMessage$ + "RCX = " + Str(ErrorRegister(#PB_OnError_RCX)) + #CRLF$
      ErrorMessage$ + "RDX = " + Str(ErrorRegister(#PB_OnError_RDX)) + #CRLF$
      ErrorMessage$ + "RBP = " + Str(ErrorRegister(#PB_OnError_RBP)) + #CRLF$
      ErrorMessage$ + "RSI = " + Str(ErrorRegister(#PB_OnError_RSI)) + #CRLF$
      ErrorMessage$ + "RDI = " + Str(ErrorRegister(#PB_OnError_RDI)) + #CRLF$
      ErrorMessage$ + "RSP = " + Str(ErrorRegister(#PB_OnError_RSP)) + #CRLF$
      ErrorMessage$ + "Display of registers R8-R15 skipped."         + #CRLF$
 
  PrintN(ErrorMessage$)
  End
 
EndProcedure

Procedure  RW_LibCurl_WriteFunction(*ptr, Size, NMemB, *Stream)
  ;retreives utf-8/ascii encoded data
  Protected SizeProper.i  = Size & 255
  Protected NMemBProper.i = NMemB
  Protected MyDataS.s
  Shared ReceivedData.s
 
  MyDataS = PeekS(*ptr, SizeProper * NMemBProper)
  ReceivedData + MyDataS
  ;Debug "> " + MyDataS
  ;Debug "# " + Str(Len(MyDataS))
  ;Debug "@ " + Str(Len(ReceivedData))
  ProcedureReturn SizeProper * NMemBProper
EndProcedure
Procedure.s RW_LibCurl_GetData()
  Shared ReceivedData.s
  Protected ReturnData.s
 
  ReturnData.s = ReceivedData.s
  ReceivedData.s = ""
 
  ProcedureReturn ReturnData.s
EndProcedure



OpenConsole()
Library = OpenLibrary(#PB_Any,"libcurl.so")
If Library
  
  curl = CallCFunction(Library,"curl_easy_init")  
  If curl
    OnErrorCall(@ErrorHandler())
    PrintN("curl is open! --> h="+curl)
 
    *opt_func = GetFunction(Library,"curl_easy_setopt")
    *pef_func = GetFunction(Library,"curl_easy_perform")   

    PrintN("@"+*opt_func)
    PrintN("@"+*pef_func)
    
    ;CallFunctionFast(*opt_func,curl,10002,#NULL,0) ;should work --> IS NOT
    ;CallFunctionFast(*opt_func,curl,64,0) ;should work --> IS NOT
    ;CallFunctionFast(*opt_func,curl,81,0) ;should work --> IS NOT
    CallCFunctionFast(*opt_func,curl,20011,@RW_LibCurl_WriteFunction()) ;should work --> IS NOT
    
    CallCFunctionFast(*pef_func,curl)
    PrintN(RW_LibCurl_GetData())
    CallCFunction(Library,"curl_easy_cleanup",curl)
  EndIf
  CloseLibrary(Library)
EndIf
Terminal Output:

Code: Select all

ehead@wsdebnix:/home/ehead/curl# pbcompiler -l ct.pb -e run.me

******************************************
PureBasic 5.10 Beta 3 (Linux - x64)
******************************************

Loading external modules...
Starting compilation...
119 lines processed.
Creating the executable.

- Feel the ..PuRe.. Power -

ehead@wsdebnix:/home/ehead/curl# ./run.me
curl is open! --> h=30454176
@140376225321408
@140376225321168
A program error was detected:

Error Message:   Segmentation violation
Error Code:      11
Code Address:    140376225320740
Target Address:  1672
Sourcecode line: 112
Sourcecode file: ct.pb

Register content:
RAX = 35777
RBX = 0
RCX = 115056
RDX = 140376231132824
RBP = 0
RSI = 0
RDI = 140376231132736
RSP = 140734046701376
Display of registers R8-R15 skipped.
my currently installed curl librarys:

Code: Select all

ehead@wsdebnix:/home/ehead/curl# ldconfig -p | grep curl
        libcurl.so.4 (libc6,x86-64) => /usr/lib/libcurl.so.4
        libcurl.so (libc6,x86-64) => /usr/lib/libcurl.so
        libcurl-gnutls.so.4 (libc6,x86-64) => /usr/lib/libcurl-gnutls.so.4
Thanks!
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

Re: libcurl, always segmentation violation

Post by Deluxe0321 »

Fixed it by myself.
You need to link the library the same way like gcc does (stupid me :D).
Also, optional parameters need to be nulled while importing.

Small example:

Code: Select all

Procedure curl_read_callback(*buffer,size.i,nitems.i,*instream)
  Shared ReceivedData.s
  PrintN("recv: "+Str(size.i * nitems.i)+" Byte")
  MyData.s = PeekS(*buffer, size.i * nitems.i)
  ReceivedData + MyData.s
  ProcedureReturn size.i * nitems.i
EndProcedure

#CURLOPT_VERBOSE      = 41
#CURLOPT_WRITEFUNCTION = 20011
#CURLOPT_URL		  = 10002

ImportC "/usr/lib/libcurl.so"
ImportC "-lcurl" : EndImport

ImportC "/usr/lib/libcurl.so"
	curl_easy_init()
	curl_easy_setopt(*curl,opt = #NULL,*parameter = #NULL)
	curl_easy_perform(*curl)
	curl_easy_cleanup(*curl)
EndImport

*memory = AllocateMemory(StringByteLength("http://www.purebasic.fr/english/",#PB_Ascii)+Sizeof(Character))
PokeS(*memory,"http://www.purebasic.fr/english/")

*callback = @curl_read_callback()

*curl = curl_easy_init()
If *curl
    OpenConsole()
    PrintN("curl is open! --> h="+*curl)
    ;curl_easy_setopt(*curl,#CURLOPT_VERBOSE)
    curl_easy_setopt(*curl,#CURLOPT_URL,*memory)
    curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION,*callback)
    curl_easy_perform(*curl)
    PrintN("Data: "+ReceivedData.s)
    curl_easy_cleanup(*curl)
Endif
End
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: libcurl, always segmentation violation

Post by idle »

Glad you got it sorted

The import should be fine as

ImportC "-lcurl"
...
EndImport

the -l tells gcc to search for libcurl under /usr/lib

also I don't think you don't need to specify the nulls in the import functions, but it doesn't hurt to do so.
Windows 11, Manjaro, Raspberry Pi OS
Image
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

Re: libcurl, always segmentation violation

Post by Deluxe0321 »

Hi idle,
thank you ;) I changed it and it works fine!
Your post (http://www.purebasic.fr/english/viewtop ... 15&t=51656) was the final hint I needed to sort it out.
also I don't think you don't need to specify the nulls in the import functions, but it doesn't hurt to do so.
well, without the #NULL I get the same segmentation violation again. I don't know either, but this currently seems to be the only way.

More interesting is that:

Code: Select all

*callback = @curl_read_callback()
curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION,*callback)
is working without any problem, but

Code: Select all

curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION,@curl_read_callback())
causes a segmentation violation again ;)

Maybe a PB BUG? I don't know, but for now I'm happy that it works anyhow.

thanks,
deluxe0321
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: libcurl, always segmentation violation

Post by ts-soft »

Change your callback Procedure to ProcedureC :wink:
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

Re: libcurl, always segmentation violation

Post by Deluxe0321 »

I already tried that, still the same ;)

Code: Select all

curl is open! --> h=22863584
A program error was detected:

Error Message:   Segmentation violation
Error Code:      11
Code Address:    139779043827997
Target Address:  20011
Sourcecode line: 98 ;(+ the on error stuff in the first post ) is this line --> curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION,@curl_read_callback())
Sourcecode file: ct.pb

Register content:
RAX = 139779043827997
RBX = 0
RCX = 0
RDX = 140734346481103
RBP = 0
RSI = 20011
RDI = 22863584
RSP = 140734346480896
Display of registers R8-R15 skipped.
My guess is that this could be a bug, because the Target Adress is 20011, which is #CURLOPT_WRITEFUNCTION
not the actual pointer to the procedure.


Edit, the same happens if I try to "point" a string "statically"

Code: Select all

ProcedureC curl_read_callback(*buffer,size.i,nitems.i,*instream)
  Shared ReceivedData.s
  PrintN("recv: "+Str(size.i *nitems.i)+" Byte")
  MyData.s = PeekS(*buffer, size.i * nitems.i)
  ReceivedData + MyData.s
  ProcedureReturn size.i * nitems.i
EndProcedure

#CURLOPT_VERBOSE      = 41
#CURLOPT_WRITEFUNCTION = 20011
#CURLOPT_URL		  = 10002

;ImportC "/usr/lib/libcurl.so"
;ImportC "-lcurl" : EndImport

ImportC "-lcurl" 
	curl_easy_init()
	curl_easy_setopt(*curl,opt = #NULL,*parameter = #NULL)
	curl_easy_perform(*curl)
	curl_easy_cleanup(*curl)
EndImport

*memory = AllocateMemory(StringByteLength("http://www.purebasic.fr/english/",#PB_Ascii)+Sizeof(Character))
PokeS(*memory,"http://www.purebasic.fr/english/")

*callback = @curl_read_callback()

*curl = curl_easy_init()
If *curl
    PrintN("curl is open! --> h="+*curl)
    curl_easy_setopt(*curl,#CURLOPT_URL,@"http://www.purebasic.fr/english/"); <-- CRASH 
    curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION, @curl_read_callback()); <-- CRASH 

    ;curl_easy_setopt(*curl,#CURLOPT_URL,*memory); <-- works
    ;curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION, *callback); <-- works

    curl_easy_perform(*curl)
    PrintN("Data: "+ReceivedData.s)
    curl_easy_cleanup(*curl)
Endif
//edited the code to see the problem better.
Last edited by Deluxe0321 on Thu Jan 24, 2013 1:13 am, edited 1 time in total.
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: libcurl, always segmentation violation

Post by idle »

I don't see any problems here with Ascii or unicode
you cant pass the string directly to curl when compiling in unicode with this code though

Code: Select all

ProcedureC curl_read_callback(*buffer,size.i,nitems.i,*instream)
  Shared ReceivedData.s
  PrintN("recv: "+Str(size.i *nitems.i)+" Byte")
  MyData.s = PeekS(*buffer, size.i * nitems.i,#PB_Ascii)
  ReceivedData + MyData.s
  ProcedureReturn size.i * nitems.i
EndProcedure

#CURLOPT_VERBOSE      = 41
#CURLOPT_WRITEFUNCTION = 20011
#CURLOPT_URL        = 10002

;ImportC "/usr/lib/libcurl.so"
;ImportC "-lcurl" : EndImport

ImportC "-lcurl" 
   curl_easy_init()
   curl_easy_setopt(*curl,opt = #Null,*parameter = #Null)
   curl_easy_perform(*curl)
   curl_easy_cleanup(*curl)
EndImport

len = StringByteLength("http://www.purebasic.fr/english/",#PB_Ascii)+SizeOf(Character)
*memory = AllocateMemory(len)
PokeS(*memory,"http://www.purebasic.fr/english/",len,#PB_Ascii)

*callback = @curl_read_callback()

*curl = curl_easy_init()
OpenConsole()
If *curl
    PrintN("curl is open! --> h="+*curl)
    ;curl_easy_setopt(*curl,#CURLOPT_VERBOSE)
    curl_easy_setopt(*curl,#CURLOPT_URL,*memory);@"http://www.purebasic.fr/english/"); <-- CRASH  *memory) <-- works 
    curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION, *callback);@curl_read_callback()); <-- CRASH  *callback) <-- works
    curl_easy_perform(*curl)
    PrintN("Data: "+ReceivedData.s)
    curl_easy_cleanup(*curl)
 EndIf
 
 Input()
Windows 11, Manjaro, Raspberry Pi OS
Image
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

Re: libcurl, always segmentation violation

Post by Deluxe0321 »

I don't see any problems here with Ascii or unicode
you cant pass the string directly to curl when compiling in unicode with this code though
and passing the procedure directly is working too?

I compiled the code only in ASCII.
If this is not PB releated, what else could it be?

Code: Select all

curl_easy_setopt(*curl,#CURLOPT_URL,@"http://www.purebasic.fr/english/"); <-- CRASH 
curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION, @curl_read_callback()); <-- CRASH 

;curl_easy_setopt(*curl,#CURLOPT_URL,*memory); <-- works
;curl_easy_setopt(*curl,#CURLOPT_WRITEFUNCTION, *callback); <-- works

Thank you,
deluxe0321
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: libcurl, always segmentation violation

Post by idle »

sorry was in a rush
yes both functions work with either parameter
direct address of string or *memory
and direct address of function or *callback

I tested on PB 5.04b x64 on ubuntu 12.04 with curl 7.22
Windows 11, Manjaro, Raspberry Pi OS
Image
Deluxe0321
User
User
Posts: 69
Joined: Tue Sep 16, 2008 6:11 am
Location: ger

Re: libcurl, always segmentation violation

Post by Deluxe0321 »

Hi idle,
thank you very much for helping me!

I'm using libcurl 7.21.0-2.1+squeeze2 ( http://packages.debian.org/de/squeeze/l ... penssl-dev ) on 2.6.32-5-amd64 (Debian 2.6.32-46).
Compiling the a sample code ( http://curl.haxx.se/libcurl/c/https.html ) using gcc works fine and the created binary runs as it should on the machine.

This is very obscure. I have no idea what the cause of this could be. :(
But ok, even this is a PB Bug or not, I can still use it by adressing everything "dynamicly", so I'm happy for now.

Thank you,
Deluxe0321
User avatar
Kukulkan
Addict
Addict
Posts: 1352
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: libcurl, always segmentation violation

Post by Kukulkan »

Hi,

here are some extracts from our working curl functions (Win, Lin, Mac). Maybe this helps you out?

Code: Select all

Global CURL_LIBRARYID = 0

; cURL prototypes
PrototypeC curl_easy_init()
PrototypeC curl_easy_setopt(handle.i, curlOpt, *option)
PrototypeC curl_easy_perform(handle.i)
PrototypeC curl_easy_cleanup(handle.i)
PrototypeC curl_slist_append(*curl_slist, *StringPointer)
PrototypeC curl_slist_free_all(*curl_slist)
PrototypeC curl_easy_strerror(errornum.i)

; Global handles
Global curl_easy_init.curl_easy_init
Global curl_easy_setopt.curl_easy_setopt
Global curl_easy_perform.curl_easy_perform
Global curl_easy_cleanup.curl_easy_cleanup
Global curl_slist_append.curl_slist_append
Global curl_slist_free_all.curl_slist_free_all
Global curl_easy_strerror.curl_easy_strerror

Procedure loadCurl()
  Protected LibName.s
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      LibName.s = "libcurl.so.4"
    CompilerCase #PB_OS_Windows
      LibName.s = "libcurl.dll"
    CompilerCase #PB_OS_MacOS
      LibName.s = "libcurl.dylib"
  CompilerEndSelect
  
  CURL_LIBRARYID = OpenLibrary(#PB_Any, LibName.s)
  If CURL_LIBRARYID = 0
    Debug "can not open " + LibName.s
    ProcedureReturn #False
  EndIf
  
  curl_easy_init      = GetFunction(CURL_LIBRARYID, "curl_easy_init")
  curl_easy_setopt    = GetFunction(CURL_LIBRARYID, "curl_easy_setopt")
  curl_easy_perform   = GetFunction(CURL_LIBRARYID, "curl_easy_perform")
  curl_easy_cleanup   = GetFunction(CURL_LIBRARYID, "curl_easy_cleanup")
  curl_slist_append   = GetFunction(CURL_LIBRARYID, "curl_slist_append")
  curl_slist_free_all = GetFunction(CURL_LIBRARYID, "curl_slist_free_all")
  curl_easy_strerror  = GetFunction(CURL_LIBRARYID, "curl_easy_strerror")
  
  ProcedureReturn #True
EndProcedure

; How we did our CURL Callbacks
ProcedureC.i RW_LibCurl_WriteStrFunction(*ptr, Size, NMemB, *Stream.structResult)
ProcedureC.i RW_LibCurl_FileWriterFunction(*ptr, Size, NMemB, *ctx.CURL_Write_ctx)
ProcedureC.i RW_LibCurl_ReadStrFunction(*ptr, Size, NMemB, *context.upload_status)

; How we set them using curl_easy_setopt
Ret.i = curl_easy_setopt(curl_Handle.i, #CURLOPT_WRITEFUNCTION, @RW_LibCurl_WriteStrFunction())
Ret.i = curl_easy_setopt(curl_Handle.i, #CURLOPT_WRITEFUNCTION, @RW_LibCurl_FileWriterFunction())
Ret.i = curl_easy_setopt(curl_Handle.i, #CURLOPT_READFUNCTION, @RW_LibCurl_ReadStrFunction())
Ret.i = curl_easy_setopt(curl_Handle.i, #CURLOPT_WRITEDATA, @curlData)

; How we set connection url
URL.s = "http://www.yahoo.com"
Ret.i = _curl_set_string_opt(curl_Handle.i, #CURLOPT_URL, URL.s)
I just copied this out from our sources. I think it should help you out on your issues.

Best,

Kukulkan
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: libcurl, always segmentation violation

Post by Shardik »

idle wrote:The import should be fine as

ImportC "-lcurl"
...
EndImport

the -l tells gcc to search for libcurl under /usr/lib
ImportC "-lcurl" only finds libcurl if the library libcurl.so can be found in /usr/lib. A libcurl.so.3 or libcurl.so.4 isn't sufficient. In order to obtain libcurl.so, the developer version has to be installed with:
sudo apt-get install libcurl4-openssl-dev
or
sudo apt-get install libcurl4-gnutls-dev
Fred
Administrator
Administrator
Posts: 16664
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: libcurl, always segmentation violation

Post by Fred »

Commenting the 'Procedure ErrorHandler()' make it work, so it's probably related to our OnError handling on Linux
Post Reply