How to catch SIGPIPE

Windows specific questions.
Post Reply
Iczer
Posts: 99
Joined: Jul 04, 2017 18:09

How to catch SIGPIPE

Post by Iczer »

It seems one of curl- related libraries sometimes generate SIGPIPE signal and (in multy-thread) I need to catch it and silently dispose myself to prevent my app from crashing. Bu how I can install signal handler in FreeBasic?
I tried to get inspiration from:

Code: Select all

Here's an example program that installs a SIGSEGV handler and prints a stacktrace to stderr 
when it segfaults. 
The baz() function here causes the segfault that triggers the handler:

#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>


void handler(int sig) {
  void *array[10];
  size_t size;

  // get void*'s for all entries on the stack
  size = backtrace(array, 10);

  // print out all the frames to stderr
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}

void baz() {
 int *foo = (int*)-1; // make a bad pointer
  printf("%d\n", *foo);       // causes segfault
}

void bar() { baz(); }
void foo() { bar(); }


int main(int argc, char **argv) {
  signal(SIGSEGV, handler);   // install our handler
  foo(); // this will call foo, bar, and baz.  baz segfaults.
}

Compiling with -g -rdynamic gets you symbol info in your output, 
which glibc can use to make a nice stacktrace:

$ gcc -g -rdynamic ./test.c -o test

Executing this gets you this output:

$ ./test
Error: signal 11:
./test(handler+0x19)[0x400911]
/lib64/tls/libc.so.6[0x3a9b92e380]
./test(baz+0x14)[0x400962]
./test(bar+0xe)[0x400983]
./test(foo+0xe)[0x400993]
./test(main+0x28)[0x4009bd]
/lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3a9b91c4bb]
./test[0x40086a]

This shows the load module, offset, and function that each frame in the stack came from. 
Here you can see the signal handler on top of the stack, and the libc functions before main
 in addition to main, foo, bar, and baz.
But failed to implement...
There also need to get a stack trace from crash - to debug it
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: How to catch SIGPIPE

Post by VANYA »

signal(SIGSEGV, handler)
Does it work on Windows? I thought this could only work on Linux

For Windows, maybe this SetUnhandledExceptionFilter will work?
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to catch SIGPIPE

Post by dodicat »

I can get a simple signal in windows by:

Code: Select all


declare sub signal cdecl alias "signal"(as integer,as sub(as integer))
declare function  raise cdecl alias "raise"(as integer) as integer 'unused
#define SIGSEGV 11

sub sighandle(sig as integer)
      print "Error, signal ";sig
      print "Please wait 2 seconds"
      sleep 2000
end sub


signal(SIGSEGV, @sighandle)

dim as integer ptr i
print *i
print "OK"
sleep

 
Iczer
Posts: 99
Joined: Jul 04, 2017 18:09

Re: How to catch SIGPIPE

Post by Iczer »

Thanks!
I tried to search SIGPIPE and others signals values/defines in freebasic includes but no luck...
I found it in standalone mingw-w64 includes, but there it defined only for posix. Will it work in windows?
include in question:

Code: Select all

/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the mingw-w64 runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */
#ifndef _INC_SIGNAL
#define _INC_SIGNAL

#include <crtdefs.h>
#include <pthread_signal.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef _SIG_ATOMIC_T_DEFINED
#define _SIG_ATOMIC_T_DEFINED
  typedef int sig_atomic_t;
#endif

#define NSIG 23

#define SIGINT 2
#define SIGILL 4
#define SIGABRT_COMPAT 6
#define SIGFPE 8
#define SIGSEGV 11
#define SIGTERM 15
#define SIGBREAK 21
#define SIGABRT 22       /* used by abort, replace SIGIOT in the future */
#define SIGABRT2 22

#ifdef _POSIX
#define	SIGHUP	1	/* hangup */
#define	SIGQUIT	3	/* quit */
#define	SIGTRAP	5	/* trace trap (not reset when caught) */
#define SIGIOT  6       /* IOT instruction */
#define	SIGEMT	7	/* EMT instruction */
#define	SIGKILL	9	/* kill (cannot be caught or ignored) */
#define	SIGBUS	10	/* bus error */
#define	SIGSYS	12	/* bad argument to system call */
#define	SIGPIPE	13	/* write on a pipe with no one to read it */
#ifdef __USE_MINGW_ALARM
#define	SIGALRM	14	/* alarm clock */
#endif
#endif

  typedef	void (*__p_sig_fn_t)(int);

#define SIG_DFL (__p_sig_fn_t)0
#define SIG_IGN (__p_sig_fn_t)1
#define SIG_GET (__p_sig_fn_t)2
#define SIG_SGE (__p_sig_fn_t)3
#define SIG_ACK (__p_sig_fn_t)4
#define SIG_ERR (__p_sig_fn_t)-1

  extern void **__cdecl __pxcptinfoptrs(void);
#define _pxcptinfoptrs (*__pxcptinfoptrs())

  __p_sig_fn_t __cdecl signal(int _SigNum,__p_sig_fn_t _Func);
  int __cdecl raise(int _SigNum);

#ifdef __cplusplus
}
#endif
#endif
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to catch SIGPIPE

Post by dodicat »

You could try
CaptureStackBackTrace from windows.bi
in my sighandle sub.
parameter 3 is an array of any ptr, but this is clutching at straws IMO in Windows.
I only get one result from array(10).

Code: Select all

Error, signal  11
Please wait 2 seconds
 0            4200203
 1            0
 2            0
 3            0
 4            0
 5            0
 6            0
 7            0
 8            0
 9            0
 10           0
Press any key to continue . . . 
You may have to slog through
https://learn.microsoft.com/en-us/windo ... n-handling
Freebasic usually gets there with a bit of work.
adeyblue
Posts: 300
Joined: Nov 07, 2019 20:08

Re: How to catch SIGPIPE

Post by adeyblue »

Iczer wrote: Feb 28, 2023 21:53 Thanks!
I tried to search SIGPIPE and others signals values/defines in freebasic includes but no luck...

Code: Select all

#define	SIGPIPE	13
extern "C"
	type signalSubType as sub(byval as long)
	declare function signal(byval as long, byval as signalSubType) as signalSubType
end extern

sub HandleSignal(byval sig as long)
      print "Error, signal ";sig
      print "Please wait 2 seconds"
      sleep 2000
end sub

signal(SIGPIPE, @HandleSignal)
Or you just might be able to set CURLOPT_NOSIGNAL to 1 and bypass it all together.
dodicat wrote: Mar 01, 2023 9:52 You could try
CaptureStackBackTrace from windows.bi
in my sighandle sub.
parameter 3 is an array of any ptr, but this is clutching at straws IMO in Windows.
I only get one result from array(10).
You have to compile with -eunwindinfo (I think that's what it's called) in 64-bit to make it work properly.

Turning the addresses into function names requires compiling with -g, and either:
- custom code to read the symbol table if using -gen gas64
- external dll like mgwhelp.dll from Dr Mingw or libdwarf if compiling with -gen gcc
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: How to catch SIGPIPE

Post by marcov »

dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to catch SIGPIPE

Post by dodicat »

Signal can only have one of 8 values in fb windows.
crt abort is value 22

Code: Select all

#include "crt.bi"

declare function signal cdecl alias "signal"(as integer,as sub(as integer)) as any ptr
declare function  raise cdecl alias "raise"(as integer) as integer 

sub sighandle(sig as integer)
      print "Error, signal ";sig
      if sig=22 then print "Please press any key . . .": sleep
end sub

for n as long=0 to 31
    if signal(n,@sighandle)=0 then raise(n)
next

 
Post Reply