Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-05

exceptions

12 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Rainer Stratmann

The send function causes sometimes an exception (permission denied).

try
 l := send( ... )
except
 l := 0;
end;

This does not work.

The Program always stops in case of an exception. With exitcode 13 (permission denied).

What do I have to do that the program continuous execution also when exceptions occurs?

Rainer

Reply by email

Jonas Maebe
to Rainer Stratmann
Rainer Stratmann wrote
The send function causes sometimes an exception (permission denied).

Which send function? The one of the sockets unit? If never raises an exception. It only sets socketerror. If you are not talking about that send function, which one do you mean? And how does it raise an exception?

Jonas

Reply by email

Rainer Stratmann
to Jonas Maebe

Yes, the send function from the socket unit.

Situation:

Connection is established.
Client closes connection
Server wants to sent data with send.
Program stops with errorcode 13 (I found out that this is the linux errorcode for permission denied).

The error is reproduceable.

I thought that may a special setsockopt can also be a solution for this.

Rainer

Jonas Maebe wrote 13 lines
On 26 May 2009, at 22:01, Rainer Stratmann wrote: > The send function causes sometimes an exception (permission denied). Which send function? The one of the sockets unit? If never raises an exception. It only sets socketerror. If you are not talking about that send function, which one do you mean? And how does it raise an exception? Jonas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Rainer Stratmann
Rainer Stratmann wrote
Yes, the send function from the socket unit.

Well, as I said: it does not raise any exceptions.

Show quoted text 10 lines
Situation: Connection is established. Client closes connection Server wants to sent data with send. Program stops with errorcode 13 (I found out that this is the linux errorcode for permission denied). The error is reproduceable.

That's all quite possible, but it's not due to the send function raising an exception (as you also noticed, since adding try/except around the send function did not catch anything.

The socket unit calls through to unix routines (either via libc or via syscalls), and these set errno based on the result. However, that result should not propagate into inoutres/ioresult (which is what could make the program exit with that error at some point if you later on call e.g. writeln).

Jonas

Reply by email

Rainer Stratmann
to Jonas Maebe
Jonas Maebe wrote
Well, as I said: it does not raise any exceptions.

Would it be possible to catch that exception?
With the try except block?
Are other functions existing to catch linux exceptions?

Show quoted text 5 lines
The socket unit calls through to unix routines (either via libc or via syscalls), and these set errno based on the result. However, that result should not propagate into inoutres/ioresult (which is what could make the program exit with that error at some point if you later on call e.g. writeln).

I am sure that the exception comes from the send call. Because the next debug calls are not executed (print something on the screen). Also the errorcode 13 makes sense.
The result is not directly shown by freepascal.
But a calling program which does not fail shows the result.

Rainer

Show quoted text 5 lines
Jonas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Vincent Snijders
to Rainer Stratmann
Rainer Stratmann wrote 7 lines
Am Dienstag, 26. Mai 2009 22:27 schrieb Jonas Maebe: > Well, as I said: it does not raise any exceptions. Would it be possible to catch that exception? With the try except block? Are other functions existing to catch linux exceptions?

No, you cannot catch exception that are not raised.

Vincent

Reply by email

Rainer Stratmann
to Vincent Snijders
Vincent Snijders wrote 9 lines
Rainer Stratmann schreef: > Am Dienstag, 26. Mai 2009 22:27 schrieb Jonas Maebe: >> Well, as I said: it does not raise any exceptions. > > Would it be possible to catch that exception? > With the try except block? > Are other functions existing to catch linux exceptions? No, you cannot catch exception that are not raised.

What does 'raised' exactly mean?

Rainer

Vincent _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Rainer Stratmann
Rainer Stratmann wrote 11 lines
Am Mittwoch, 27. Mai 2009 11:45 schrieb Vincent Snijders: > Rainer Stratmann schreef: >> Am Dienstag, 26. Mai 2009 22:27 schrieb Jonas Maebe: >>> Well, as I said: it does not raise any exceptions. >> >> Would it be possible to catch that exception? >> With the try except block? >> Are other functions existing to catch linux exceptions? > > No, you cannot catch exception that are not raised. What does 'raised' exactly mean?

http://www.freepascal.org/docs-html/ref/refse73.html

Please provide a compilable sample that demonstrates the problem you are having. I'm guessing you can "solve" it by adding the sysutils unit to your uses clause (because currently you're probably getting a plain run time error, and using the sysutils unit means that it will be converted into an exception that you can catch), but that would just be a hack. You probably also would have to put the try/catch around the next debugging writeln, and not around the send() call to catch the exception (because send() does not cause any inoutres checks, but writeln() does)

I really have no idea how the error result of send() could end up in inoutres though (which is, I think, the only way that could cause the RTL to produce a run time error in response to a failed send() call). There are variants of the socket routines that work on text files and that do set inoutres, but send() is not one of them.

So please, provide source code (even if some hack seems to solve the problem) so we don't have to send 10 more mails guessing about what you might be doing and what might be going wrong.

Jonas

Reply by email

Rainer Stratmann
to Jonas Maebe

Shrinked down example of the program.
Rainer

program serverclient;

uses
baseunix ,
sockets,

     crt;
const port_program = 12021;
procedure memclr( p : pointer ; len : longint );
var x : longint;
begin
 for x := 1 to len do begin
  byte( p^ ) := 0;
  inc( p );
 end;
end;
procedure setsockaddr( var sa : tsockaddr ; adr : string ; port : longint );
begin
 memclr( @sa , sizeof( sa ) );
 sa.sin_family := AF_INET;
 sa.sin_addr   := strtonetaddr( adr );
 sa.sin_port   := htons( port );
end;
procedure setnonblockingsocket( s : integer );
var  arg : longint;
begin
  arg := fpfcntl( s , F_GETFL );
  if arg >= 0 then begin
   arg := arg or O_NONBLOCK;
   fpfcntl( s , F_SETFL , arg );
  end;
end;
procedure ip_client( ipadress : string );
var
 inetaddr_client_remote : tsockaddr;
 c_socket : integer;
 c : longint;
begin
 setsockaddr( inetaddr_client_remote , ipadress , port_program );
 c_socket := fpsocket( PF_INET , SOCK_STREAM , 0 );
 if c_socket >= 0 then begin
   writeln( 'open socket' );
   setnonblockingsocket( c_socket ); // nonblocking connect call
   repeat
     c := fpconnect( c_socket , @inetaddr_client_remote ,
sizeof( inetaddr_client_remote ) );
   until c = 0;
   writeln( 'connected' );
   crt.delay( 1000 );
   closesocket( c_socket );
   writeln( 'closed' );
 end;
end;
procedure ip_server;
var
  inetaddr_server_bind   : tsockaddr;
  inetaddr_server_accept : tsockaddr;
  alength : integer;
  l : longint;
  c : byte = 0;
  s_socket     : integer;
  s_acc_socket : integer;
  s_bind       : longint;
  s_listen     : longint;
begin
    clrscr;
    s_socket := fpsocket( PF_INET , SOCK_STREAM , 0 );
    if s_socket  -1 then begin
      setnonblockingsocket( s_socket );
      setsockaddr( inetaddr_server_bind , '' , port_program );
      s_bind := fpbind( s_socket , @inetaddr_server_bind ,
sizeof( inetaddr_server_bind ) );
      if s_bind  -1 then begin
        s_listen := fplisten( s_socket , 0 ); // socket , warteschlange
        if s_listen = 0 then begin
          alength := sizeof( inetaddr_server_accept );
          repeat
            // wait for incoming connection
            s_acc_socket := fpaccept( s_socket , @inetaddr_server_accept ,
@alength );
            write( '.' );
            delay( 300 ); // little delay
          until ( s_acc_socket >= 0 ) or keypressed;
          if s_acc_socket >= 0 then begin
            repeat
              // Exception
              l := fpsend( s_acc_socket , @c , sizeof( c ) , 0 );
              // Exception
              write( '*' ); // <- this does NOT making the exception
              delay( 300 ); // little delay
            until keypressed;
            closesocket( s_acc_socket );
          end;
        end;
      end;
    end;
end;
const
 server = true;
// server = false;
begin
  if server then ip_server
            else ip_client ( '192.168.178.21' ); // ip address of the server
end.
Jonas Maebe wrote 41 lines
On 27 May 2009, at 19:24, Rainer Stratmann wrote: > Am Mittwoch, 27. Mai 2009 11:45 schrieb Vincent Snijders: >> Rainer Stratmann schreef: >>> Am Dienstag, 26. Mai 2009 22:27 schrieb Jonas Maebe: >>>> Well, as I said: it does not raise any exceptions. >>> >>> Would it be possible to catch that exception? >>> With the try except block? >>> Are other functions existing to catch linux exceptions? >> >> No, you cannot catch exception that are not raised. > > What does 'raised' exactly mean? http://www.freepascal.org/docs-html/ref/refse73.html Please provide a compilable sample that demonstrates the problem you are having. I'm guessing you can "solve" it by adding the sysutils unit to your uses clause (because currently you're probably getting a plain run time error, and using the sysutils unit means that it will be converted into an exception that you can catch), but that would just be a hack. You probably also would have to put the try/catch around the next debugging writeln, and not around the send() call to catch the exception (because send() does not cause any inoutres checks, but writeln() does) I really have no idea how the error result of send() could end up in inoutres though (which is, I think, the only way that could cause the RTL to produce a run time error in response to a failed send() call). There are variants of the socket routines that work on text files and that do set inoutres, but send() is not one of them. So please, provide source code (even if some hack seems to solve the problem) so we don't have to send 10 more mails guessing about what you might be doing and what might be going wrong. Jonas _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Rainer Stratmann
Rainer Stratmann wrote
Shrinked down example of the program.

strace shows this:

accept(3, {sa_family=AF_INET, sin_port=htons(48134), sin_addr=inet_addr("xxx.xxx.xxx.xxx")}, [16]) = 4
write(1, ".", 1) = 1
select(0, NULL, NULL, NULL, {0, 300000}) = 0 (Timeout) sendto(4, "\0", 1, 0, NULL, 0) = 1
write(1, "*", 1) = 1
select(0, NULL, NULL, NULL, {0, 300000}) = 0 (Timeout) select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout) sendto(4, "\0", 1, 0, NULL, 0) = 1
write(1, "*", 1) = 1
select(0, NULL, NULL, NULL, {0, 300000}) = 0 (Timeout) select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout) sendto(4, "\0", 1, 0, NULL, 0) = -1 ECONNRESET (Connection reset by peer)
write(1, "*", 1) = 1
select(0, NULL, NULL, NULL, {0, 300000}) = 0 (Timeout) select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout) sendto(4, "\0", 1, 0, NULL, 0) = -1 EPIPE (Broken pipe) --- SIGPIPE (Broken pipe) @ 0 (0) ---
+++ killed by SIGPIPE +++

It's killed by SIGPIPE. SIGPIPE is signal number 13. This signal is not caught by the RTL, and hence it's not translated into a Pascal exception.

If you don't want SIGPIPE signals, use the MSG_NOSIGNAL flag (note that this flag is not portable to all Unix-like systems). In that case, fpsend() will return -1 and fpgeterrno will be set to ESysEPIPE in case of a broken pipe. See "man send" for more information.

Note that you are using fpsend(), and not send() as you said earlier. There is a big difference between these two routines. Also note that you are using it wrongly, because you are not checking for ESysEINTR, meaning that you can easily get data loss. You have to use something like this:

repeat
   l:=fpsend(handle,bufptr,bufpos,0);
until (l-1) or (fpgeterrno  ESysEINTR);

You also have to make similar changes to your receiving side (in real world programs), and to any other call to unix functions whose man page states that they can return EINTR.

Jonas

Reply by email

JoshyFun
to Rainer Stratmann: Shrinked down example of the program. Rainer program serverclient; uses crt; const…

Hello FPC-Pascal,

Thursday, May 28, 2009, 9:58:23 PM, you wrote:

RS> Shrinked down example of the program.
RS> Rainer
[...]
RS> procedure memclr( p : pointer ; len : longint );
RS> var x : longint;
RS> begin
RS>  for x := 1 to len do begin
RS>   byte( p^ ) := 0;
RS>   inc( p );
RS>  end;
RS> end;

Aside from the socket problem, can somebody explain me this line:

RS>   byte( p^ ) := 0;
????????????? from my point of view it should be "PBYTE(P)^:=0;" am I
missing something ?
Best regards, JoshyFun

Reply by email

Jonas Maebe
to JoshyFun
JoshyFun wrote 14 lines
Hello FPC-Pascal, Thursday, May 28, 2009, 9:58:23 PM, you wrote: RS> Shrinked down example of the program. RS> Rainer [...] RS> procedure memclr( p : pointer ; len : longint ); Aside from the socket problem, can somebody explain me this line: RS> byte( p^ ) := 0; ????????????? from my point of view it should be "PBYTE(P)^:=0;" am I missing something ?

pbyte(p)^ and byte(p^) are the same thing in Pascal.

Jonas

Reply by email