70
70
int mkstemp (char * );
71
71
#endif
72
72
73
+ #define PerlIO_lockcnt (f ) (((PerlIOl*)(f))->head->flags)
74
+
73
75
/* Call the callback or PerlIOBase, and return failure. */
74
76
#define Perl_PerlIO_or_Base (f , callback , base , failure , args ) \
75
77
if (PerlIOValid(f)) { \
@@ -583,7 +585,7 @@ PerlIO_allocate(pTHX)
583
585
last = (PerlIOl * * ) (f );
584
586
for (i = 1 ; i < PERLIO_TABLE_SIZE ; i ++ ) {
585
587
if (!((++ f )-> next )) {
586
- f -> flags = 0 ;
588
+ f -> flags = 0 ; /* lockcnt */
587
589
f -> tab = NULL ;
588
590
f -> head = f ;
589
591
return (PerlIO * )f ;
@@ -595,7 +597,7 @@ PerlIO_allocate(pTHX)
595
597
return NULL ;
596
598
}
597
599
* last = (PerlIOl * ) f ++ ;
598
- f -> flags = 0 ;
600
+ f -> flags = 0 ; /* lockcnt */
599
601
f -> tab = NULL ;
600
602
f -> head = f ;
601
603
return (PerlIO * ) f ;
@@ -782,8 +784,16 @@ PerlIO_pop(pTHX_ PerlIO *f)
782
784
if ((* l -> tab -> Popped ) (aTHX_ f ) != 0 )
783
785
return ;
784
786
}
785
- * f = l -> next ;
786
- Safefree (l );
787
+ if (PerlIO_lockcnt (f )) {
788
+ /* we're in use; defer freeing the structure */
789
+ PerlIOBase (f )-> flags = PERLIO_F_CLEARED ;
790
+ PerlIOBase (f )-> tab = NULL ;
791
+ }
792
+ else {
793
+ * f = l -> next ;
794
+ Safefree (l );
795
+ }
796
+
787
797
}
788
798
}
789
799
@@ -1488,6 +1498,9 @@ Perl_PerlIO_close(pTHX_ PerlIO *f)
1488
1498
const int code = PerlIO__close (aTHX_ f );
1489
1499
while (PerlIOValid (f )) {
1490
1500
PerlIO_pop (aTHX_ f );
1501
+ if (PerlIO_lockcnt (f ))
1502
+ /* we're in use; the 'pop' deferred freeing the structure */
1503
+ f = PerlIONext (f );
1491
1504
}
1492
1505
return code ;
1493
1506
}
@@ -2518,6 +2531,38 @@ typedef struct {
2518
2531
int oflags ; /* open/fcntl flags */
2519
2532
} PerlIOUnix ;
2520
2533
2534
+ static void
2535
+ S_lockcnt_dec (pTHX_ const void * f )
2536
+ {
2537
+ PerlIO_lockcnt ((PerlIO * )f )-- ;
2538
+ }
2539
+
2540
+
2541
+ /* call the signal handler, and if that handler happens to clear
2542
+ * this handle, free what we can and return true */
2543
+
2544
+ static bool
2545
+ S_perlio_async_run (pTHX_ PerlIO * f ) {
2546
+ ENTER ;
2547
+ SAVEDESTRUCTOR_X (S_lockcnt_dec , (void * )f );
2548
+ PerlIO_lockcnt (f )++ ;
2549
+ PERL_ASYNC_CHECK ();
2550
+ if ( !(PerlIOBase (f )-> flags & PERLIO_F_CLEARED ) )
2551
+ return 0 ;
2552
+ /* we've just run some perl-level code that could have done
2553
+ * anything, including closing the file or clearing this layer.
2554
+ * If so, free any lower layers that have already been
2555
+ * cleared, then return an error. */
2556
+ while (PerlIOValid (f ) &&
2557
+ (PerlIOBase (f )-> flags & PERLIO_F_CLEARED ))
2558
+ {
2559
+ const PerlIOl * l = * f ;
2560
+ * f = l -> next ;
2561
+ Safefree (l );
2562
+ }
2563
+ return 1 ;
2564
+ }
2565
+
2521
2566
int
2522
2567
PerlIOUnix_oflags (const char * mode )
2523
2568
{
@@ -2721,7 +2766,10 @@ SSize_t
2721
2766
PerlIOUnix_read (pTHX_ PerlIO * f , void * vbuf , Size_t count )
2722
2767
{
2723
2768
dVAR ;
2724
- const int fd = PerlIOSelf (f , PerlIOUnix )-> fd ;
2769
+ int fd ;
2770
+ if (PerlIO_lockcnt (f )) /* in use: abort ungracefully */
2771
+ return -1 ;
2772
+ fd = PerlIOSelf (f , PerlIOUnix )-> fd ;
2725
2773
#ifdef PERLIO_STD_SPECIAL
2726
2774
if (fd == 0 )
2727
2775
return PERLIO_STD_IN (fd , vbuf , count );
@@ -2744,7 +2792,9 @@ PerlIOUnix_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
2744
2792
}
2745
2793
return len ;
2746
2794
}
2747
- PERL_ASYNC_CHECK ();
2795
+ /* EINTR */
2796
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
2797
+ return -1 ;
2748
2798
}
2749
2799
/*NOTREACHED*/
2750
2800
}
@@ -2753,7 +2803,10 @@ SSize_t
2753
2803
PerlIOUnix_write (pTHX_ PerlIO * f , const void * vbuf , Size_t count )
2754
2804
{
2755
2805
dVAR ;
2756
- const int fd = PerlIOSelf (f , PerlIOUnix )-> fd ;
2806
+ int fd ;
2807
+ if (PerlIO_lockcnt (f )) /* in use: abort ungracefully */
2808
+ return -1 ;
2809
+ fd = PerlIOSelf (f , PerlIOUnix )-> fd ;
2757
2810
#ifdef PERLIO_STD_SPECIAL
2758
2811
if (fd == 1 || fd == 2 )
2759
2812
return PERLIO_STD_OUT (fd , vbuf , count );
@@ -2768,7 +2821,9 @@ PerlIOUnix_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
2768
2821
}
2769
2822
return len ;
2770
2823
}
2771
- PERL_ASYNC_CHECK ();
2824
+ /* EINTR */
2825
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
2826
+ return -1 ;
2772
2827
}
2773
2828
/*NOTREACHED*/
2774
2829
}
@@ -2803,7 +2858,9 @@ PerlIOUnix_close(pTHX_ PerlIO *f)
2803
2858
code = -1 ;
2804
2859
break ;
2805
2860
}
2806
- PERL_ASYNC_CHECK ();
2861
+ /* EINTR */
2862
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
2863
+ return -1 ;
2807
2864
}
2808
2865
if (code == 0 ) {
2809
2866
PerlIOBase (f )-> flags &= ~PERLIO_F_OPEN ;
@@ -3276,8 +3333,11 @@ SSize_t
3276
3333
PerlIOStdio_read (pTHX_ PerlIO * f , void * vbuf , Size_t count )
3277
3334
{
3278
3335
dVAR ;
3279
- FILE * const s = PerlIOSelf ( f , PerlIOStdio ) -> stdio ;
3336
+ FILE * s ;
3280
3337
SSize_t got = 0 ;
3338
+ if (PerlIO_lockcnt (f )) /* in use: abort ungracefully */
3339
+ return -1 ;
3340
+ s = PerlIOSelf (f , PerlIOStdio )-> stdio ;
3281
3341
for (;;) {
3282
3342
if (count == 1 ) {
3283
3343
STDCHAR * buf = (STDCHAR * ) vbuf ;
@@ -3297,7 +3357,8 @@ PerlIOStdio_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
3297
3357
got = -1 ;
3298
3358
if (got >= 0 || errno != EINTR )
3299
3359
break ;
3300
- PERL_ASYNC_CHECK ();
3360
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
3361
+ return -1 ;
3301
3362
SETERRNO (0 ,0 ); /* just in case */
3302
3363
}
3303
3364
return got ;
@@ -3366,12 +3427,15 @@ PerlIOStdio_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
3366
3427
{
3367
3428
dVAR ;
3368
3429
SSize_t got ;
3430
+ if (PerlIO_lockcnt (f )) /* in use: abort ungracefully */
3431
+ return -1 ;
3369
3432
for (;;) {
3370
3433
got = PerlSIO_fwrite (vbuf , 1 , count ,
3371
3434
PerlIOSelf (f , PerlIOStdio )-> stdio );
3372
3435
if (got >= 0 || errno != EINTR )
3373
3436
break ;
3374
- PERL_ASYNC_CHECK ();
3437
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
3438
+ return -1 ;
3375
3439
SETERRNO (0 ,0 ); /* just in case */
3376
3440
}
3377
3441
return got ;
@@ -3533,9 +3597,12 @@ PerlIOStdio_set_ptrcnt(pTHX_ PerlIO *f, STDCHAR * ptr, SSize_t cnt)
3533
3597
IV
3534
3598
PerlIOStdio_fill (pTHX_ PerlIO * f )
3535
3599
{
3536
- FILE * const stdio = PerlIOSelf ( f , PerlIOStdio ) -> stdio ;
3600
+ FILE * stdio ;
3537
3601
int c ;
3538
3602
PERL_UNUSED_CONTEXT ;
3603
+ if (PerlIO_lockcnt (f )) /* in use: abort ungracefully */
3604
+ return -1 ;
3605
+ stdio = PerlIOSelf (f , PerlIOStdio )-> stdio ;
3539
3606
3540
3607
/*
3541
3608
* fflush()ing read-only streams can cause trouble on some stdio-s
@@ -3550,7 +3617,8 @@ PerlIOStdio_fill(pTHX_ PerlIO *f)
3550
3617
break ;
3551
3618
if (! PerlSIO_ferror (stdio ) || errno != EINTR )
3552
3619
return EOF ;
3553
- PERL_ASYNC_CHECK ();
3620
+ if (PL_sig_pending && S_perlio_async_run (aTHX_ f ))
3621
+ return -1 ;
3554
3622
SETERRNO (0 ,0 );
3555
3623
}
3556
3624
@@ -4082,7 +4150,8 @@ PerlIOBuf_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
4082
4150
PerlIO_flush (f );
4083
4151
}
4084
4152
if (b -> ptr >= (b -> buf + b -> bufsiz ))
4085
- PerlIO_flush (f );
4153
+ if (PerlIO_flush (f ) == -1 )
4154
+ return -1 ;
4086
4155
}
4087
4156
if (PerlIOBase (f )-> flags & PERLIO_F_UNBUF )
4088
4157
PerlIO_flush (f );
0 commit comments